我有一个确定列表成员资格的标准程序:
member(X, [X|_]).
member(X, [_|T]) :- member(X, T).
我不明白为什么当我提出以下问题时:
?- member(a,[a,b]).
结果是
True;
False.
我原本以为在使用第一条规则满足目标时(作为列表的头部)将返回True,这将是if的结束。看起来好像是在试图用第二条规则来满足目标并且失败了?
Prolog翻译是SWI-Prolog。
答案 0 :(得分:6)
让我们先考虑类似的问题:[编辑:执行此操作不添加添加您自己的定义; member/2
已经定义了]
?- member(a,[b,a]).
true.
在这种情况下,您将获得最佳答案:只有一个解决方案。但是当交换列表中的元素时,我们得到:
?- member(a,[a,b]).
true ;
false.
从逻辑上讲,两者都只是对查询为真的肯定。
差异的原因在于,在第二个查询中,在找到true
作为列表元素后立即给出答案a
。其余列表[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,例如,不是。
答案 1 :(得分:2)
你使用的是“;”操作员在第一个结果然后推回?我相信这是要求查询查找更多结果,因为没有它会出现错误。
答案 2 :(得分:1)
你知道Prolog的剪辑 - !
吗?
如果您将member(X, [X|_]).
更改为member(X, [X|_]) :- !.
,Prolog将不会尝试在第一个解决方案之后找到其他解决方案。