主要區別是兩者的終止屬性,只要關係中有一些循環。爲了理解這一點,我將使用一個failure-slice,它將本程序的本質劃分爲w.r.t.終止。
pred1(X,Z) :- false, parent(X,Z).
pred1(X,Z) :- parent(X,Y), pred1(Y,Z). % Z has no influence
pred2(X,Z) :- false, parent(X,Z).
pred2(X,Z) :- parent(Y,Z), pred2(X,Y). % X has no influence
對於pred1/2
,第二個參數對終止根本沒有影響,而在pred2/2
,第一個參數沒有影響。看到這一點,嘗試原始的定義:與事實:
parent(a,a).
?- pred1(b, _), false. % terminates
?- pred2(b, _), false. % loops
?- pred1(_, b), false. % loops
?- pred2(_, b), false. % terminates
的一般方法,以避免此類循環見closure/3
。
爲了完整起見,在這裏是具有某種概念的優點傳遞閉包的另一種變型:
pred3(X,Z) :- parent(X,Z).
pred3(X,Z) :- pred3(X,Y), pred3(Y,Z).
唉,其終止性質是最差的。事實上,它從未結束,如IS證明由下面的片段:
pred3(X,Z) :- false, parent(X,Z).
pred3(X,Z) :- pred3(X,Y), false, pred3(Y,Z).
在這個片段中,第一個參數是隻傳遞。所以,無論什麼爭論,程序總是會循環的!
?- pred3(b,b), false. % loops