更改参数顺序时Prolog统一破裂

问题描述

我似乎无法解决这个问题。考虑以下虚拟谓词:

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/2bar/2都没有意外的选择点:

?- foo(1,a).
true.

?- bar(a,1).
true.