让我们首先考虑一个类似的查询:[编辑:这样做无需添加您自己的定义; member/2 已定义]
?- member(a,[b,a]).
true.
在这种情况下,您会得到最佳答案:只有一种解决方案。但是当交换列表中的元素时,我们得到:
?- member(a,[a,b]).
true ;
false.
从逻辑上讲,两者都只是对查询为真的肯定。
差异的原因是,在第二个查询中,当找到a 作为列表元素时,立即给出答案true。其余列表[b] 不包含拟合元素,但尚未对此进行检查。仅根据请求(点击 SPACE 或 ;)尝试列表的其余部分,结果没有进一步的解决方案。
本质上,当计算完全完成以及仍有一些工作要做时,这个微小的差异会给你一个提示。对于简单的查询,这并没有什么不同,但在更复杂的查询中,这些开放的备选方案(选择点)可能会累积并耗尽内存。
即使没有,旧的顶层总是询问您是否想查看进一步的解决方案。
编辑:
避免询问下一个答案(如果没有)的能力很大程度上取决于实现细节。即使在同一个系统中,加载同一个程序,你也可能得到不同的结果。但是,在这种情况下,我使用的是 SWI 的内置定义 member/2,而您使用的是您自己的定义,它会覆盖内置定义。
SWI 使用以下定义作为内置定义,这在逻辑上等同于您的定义,但使 SWI 更容易避免不必要的选择点 - 但许多其他系统无法从中受益:
member(B, [C|A]) :-
member_(A, B, C).
member_(_, A, A).
member_([C|A], B, _) :-
member_(A, B, C).
让事情变得更加复杂:许多 Prolog 具有不同的顶层,当查询不包含变量时,它从不要求进一步的答案。所以在那些系统(比如 YAP)中,你会得到错误的印象。
尝试以下查询来查看:
?- member(X,[1]).
X = 1.
SWI 再次能够确定这是唯一的答案。但是 YAP,例如,不是。