为什么不同的查询返回重复的值?

时间:2019-06-20 14:52:43

标签: prolog swi-prolog

这是程序:

sibling(joe, mary).
sibling(joe, bob).
person(P) :- distinct(sibling(P, _); sibling(_, P)).

以下是查询:

person(P).

我希望得到3个名字,而不是4个。

1 个答案:

答案 0 :(得分:3)

简而言之:Prolog会跟踪所有超出目标的变量,包括无关紧要(const purpleElems = Array.from(document.querySelectorAll("li")) // find all the lis .filter(li => // filter the list of lis li.textContent.contains('Purple') // see if it has purple ) )。

问题在于您在此处引入了不是不同的自由变量。确实,如distinct/1 [swi-doc]文档中所指定。上面的功能等效于:

_

现在,如果我们使用distinct(Goal) :- findall(Goal, Goal, List), list_to_set(List, Set), member(Goal, Set). 进行简单调用,则会得到:

sibling(P, _)

或目标为逻辑“或”:

?- Goal = sibling(P, _), distinct(Goal).
Goal = sibling(joe, mary),
P = joe ;
Goal = sibling(joe, bob),
P = joe.

如您所见,?- Goal = (sibling(P, _); sibling(_, P)), distinct(Goal). Goal = (sibling(joe, mary);sibling(_4908, joe)), P = joe ; Goal = (sibling(joe, bob);sibling(_4908, joe)), P = joe ; Goal = (sibling(mary, _4904);sibling(joe, mary)), P = mary ; Goal = (sibling(bob, _4904);sibling(joe, bob)), P = bob. 被统一了两次:一次与Goal,一次与sibling(joe, mary)。唯一性过滤器不会有任何效果,因为sibling(joe, bob)mary不同。

但是,我们可以在此处定义一个辅助谓词,以摆脱这些变量,例如:

bob

然后我们可以查询:

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

或不使用?- Goal = person(P), distinct(Goal). Goal = person(joe), P = joe ; Goal = person(mary), P = mary ; Goal = person(bob), P = bob. 变量:

Goal