如何在序言中找到所有普遍事实?

How to findall for universal facts in prolog?

在序言中我可以写

 child(martha,charlotte). 
 child(charlotte,caroline). 
 child(caroline,laura). 
 child(laura,rose). 

 descend(X,Y)  :-
    child(X,Y).
 descend(X,Y)  :-
    child(X,Z), 
    descend(Z,Y).

然后写

?-  findall(X,descend(martha,X),Z).

并得到四个解

Z  =  [charlotte,caroline,laura,rose]

但是如果我再添加一个普遍的事实

likes(X,pomegranate).

并尝试

 ?-  findall(X,likes(X, pomegranate),Z).

我得到:

 Z = [_G17].

那是什么_G17? 我需要更改什么才能获得基本上所有的变量? (因为 likes(X,pomegranate) 应该意味着一切都像石榴...对吧?):

Z  =  [martha,charlotte,caroline,laura,rose]

两种解决方案。干净的解决方案是使用 table 列出您描述的宇宙中的所有 "things":

person(martha).
person(charlotte).
% etc

然后你的 "likes" 应该是:

person_likes(P, pomegranate) :-
    person(P).

您也可以尝试绕过它:

person(P) :- child(P, _).
person(P) :- child(_, P).

但这……不尽如人意?考虑一个关系数据库:您将有两个 tables:

CREATE TABLE person (
  id INTEGER PRIMARY KEY, -- usually autogenerated
  name TEXT NOT NULL
);
CREATE TABLE parent_child (
  parent_id INTEGER NOT NULL,
  child_id INTEGER NOT NULL,
  FOREIGN KEY parent_id REFERENCES person(id),
  FOREIGN KEY child_id REFERENCES person(id)
);

据我所知,为什么你不在 Prolog 中做完全相同的事情的唯一原因是大多数介绍性教程都试图引诱你并避免深入这些细节。当然,Prolog "database" 不是真正的关系数据库(例如,参数位置很重要!)。

TL;DR 在使用 Prolog 时不能不考虑 Prolog 的解析策略。