更改参数顺序时 Prolog 统一中断

Prolog unification broken when argument order is changed

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

foo(X, a) :- X < 10.
foo(X, b) :- X > 20.

咨询时:

?- foo(1, a).
true; 
false.

我不确定我是否完全理解选择点是如何创建的(也许是因为两个可能的 foo 谓词处于一种 or 关系和 Prolog只是 尝试 与两者统一?基于跟踪中的这一行: 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 (在其他序言中)有一种叫做“制表”的东西。有了它,你可以这样做:

:- 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.