主要区别在于两者的终止属性,前提是关系中有一些循环。为了理解这一点,我将使用 failure-slice 将程序缩减为 w.r.t 的本质。终止。
pred1(X,Z) :- false, parent(X,Z)。
pred1(X,
Z) :- 父级(X,Y), pred1(Y,
Z)。 %
Z 没有影响
pred2(X,Z) :- false, parent(X,Z)。
pred2(
X,Z) :- 父级(Y,Z), pred2(
X,Y)。 %
X 没有影响
对于pred1/2,第二个参数对终止完全没有影响,而在pred2/2,第一个参数没有影响。要看到这一点,请尝试使用事实的原始定义:
父母(一,一)。
?- pred1(b, _),
false。 % 终止
?- pred2(b, _),
false。 % 循环
?- pred1(_, b),
false。 % 循环
?- pred2(_, b),
false。 % 终止
请参阅closure/3,了解避免此类循环的一般方法。
为了完整起见,这里是传递闭包的另一种变体,它具有一些概念优势:
pred3(X,Z) :- parent(X,Z).
pred3(X,Z) :- pred3(X,Y), pred3(Y,Z).
唉,它的终止特性最差。事实上,它从不终止,正如以下片段所证明的那样:
pred3(X,Z) :- false, parent(X,Z)。
pred3(X,Z) :- pred3(X,Y),
false,
pred3(Y,Z)。
在这个片段中,第一个参数只被传递。所以,不管参数是什么,程序都会一直循环!
?- pred3(b,b),
false。 % 循环