问题描述
我似乎无法解决这个问题。考虑以下虚拟谓词:
foo(X,a) :- X < 10.
foo(X,b) :- X > 20.
咨询时:
?- foo(1,a).
true;
false.
我不确定我是否完全理解选择点的创建方式(也许是因为两个可能的foo
谓词处于一种 or 关系中,而Prolog只是 tries 两者要统一吗?基于跟踪中的这一行:Redo: (24) test:foo(8,a)
和随后的失败,我想是这种情况),但真正令我困惑的是为什么当改变参数顺序时它可以工作:
foo(a,X) :- X < 10.
foo(b,X) :- X > 20.
?- foo(a,1).
true.
没有选择点。我在这里想念什么?
解决方法
TL; DR:阅读您正在使用的Prolog的文档。注意“子句索引”之类的东西。
您错过了所使用的任何Prolog实现都足够聪明,无法对第二个示例中的第一个参数进行索引。因此,当您提出查询?- foo(a,Something).
时,它永远不会考虑其他子句。
但这实际上是Prolog实现的问题,而不是Prolog作为语言的问题。也许有些Prologs也可以避免第一个示例中的选择点。也许它提供了实现相同目标的不同机制。例如,SWI-Prolog(以及其他Prolog)中有一个叫做“ tabling”的东西。有了它,您可以这样做:
:- table foo/2.
foo(X,a) :- X < 10.
foo(X,b) :- X > 20.
bar(a,X) :- X < 10.
bar(b,X) :- X > 20.
现在foo/2
和bar/2
都没有意外的选择点:
?- foo(1,a).
true.
?- bar(a,1).
true.