为什么 swipl 的响应不一致?

Why the inconsistent responses from swipl?

我想了解为什么与 swipl 的互动似乎不一致。

这是一个典型的例子。假设我查阅了包含以下定义的知识库:

acc_max([H|T], A, Max) :- H  > A, acc_max(T, H, Max).
acc_max([H|T], A, Max) :- H =< A, acc_max(T, A, Max).
acc_max([], A, A).

max([H|T], Max) :- acc_max(T, H, Max).

下面是我在提示符下键入 max([0, 1, 2], X). 并按 Enter:

后屏幕的样子
?- max([0, 1, 2], X).
X = 2 ▮

(其中表示光标位置。)

请特别注意,解释器的下一个提示尚未出现。

下面是我输入 ;:

后的画面
?- max([0, 1, 2], X).
X = 2 ;
false.

?- ▮

现在终于得到口译提示了

相比之下,下面显示了我在提示符下键入 max([2, 0, 1], X). 并按 Enter:

后的屏幕外观
?- max([2, 0, 1], X).
X = 2.

?- ▮

请注意,这次我立即得到了解释器的提示 - 我不需要键入 ;。另外,没有 false.

我发现了许多其他类似的不一致(例如,有时输出 true. 会出现在屏幕上,但在其他类似情况下却不会)。

作为 Prolog 的新手,我发现这种不一致令人不安(更不用说令人沮丧了,因为它们不断提醒我我确实 毫无头绪 正在发生的事情)。

是否有一种简单的方法来合理化这些不一致?

或者,是否有一些 Prolog 实现提供比 SWI-Prolog 更一致和可预测的交互?

因此,正如@lurker 所说,这是选择点的结果 - 存在尚未评估的规则的情况,这可能会产生更多的解决方案。

让我们看一下您的示例的更简单版本,max([0,1],X).max([1,0],X).

max([0,1],X).:

这转到 acc_max([1],0,X).,它匹配两个 acc_max([H|T], A, Max) :- 规则。我们按照它们出现的顺序评估它们:

首先我们看到1 > 0为真,调用acc_max([],1,X)。这只匹配 acc_max([], A, A).,因此我们将 X 与 1 统一。我们有一个解决方案!但我们还有一个尚未评估的规则。这是你看到的地方:

X = 1 ▮

现在我们输入 ;,然后计算第二个 acc_max([H|T], A, Max) :- 规则。我们看到 1 =< 0 不是真的,所以这条规则失败了。我们现在没有规则可以尝试,所以事实证明没有更多的解决方案。因此:

X = 1 ;
false.

现在我们来看看 max([1,0],X).:

现在是 acc_max([0],1,X).。同样,我们有两个规则,按它们出现的顺序进行评估:

首先我们看到 0 > 1 不正确,所以第一条规则失败,我们评估第二条。

现在我们看到0 =< 1为真,调用acc_max([],1,X)。这仅匹配 acc_max([], A, A).,因此我们(再次)将 X 与 1 统一。我们有解决方案,这次我们没有未评估的规则(即没有未探索的选择点)。所以现在我们看到:

X = 1.

...因为在 Prolog 的 "mind" 中毫无疑问没有其他解决方案。如果您要颠倒规则的顺序:

acc_max([], A, A).
acc_max([H|T], A, Max) :- H =< A, acc_max(T, A, Max).
acc_max([H|T], A, Max) :- H  > A, acc_max(T, H, Max).

...您也会看到行为反转。

希望这有助于证明此 一致且可预测的交互,并且应该是 Prolog 的所有变体共享的交互。