我想了解为什么与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更一致和可预测的交互?
答案 0 :(得分:5)
因此,正如@lurker所说,这是选择点的结果 - 有一条规则未经评估,可能产生更多解决方案。
让我们来看一个更简单的示例版本,max([0,1],X).
vs 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的“思想”中毫无疑问,没有其他解决方案。如果您要颠倒规则的顺序:
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的所有变种共享的。