为什么 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 的所有变体共享的交互。
我想了解为什么与 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 的所有变体共享的交互。