2016-12-21 25 views

回答

0

顧名思義,earlier(X, Y, Zs)顯然應該檢查元素X是否早於列表Zs中的第一個出現Y。它種做到這一點:

?- earlier(a, b, [a, b, c, d]). 
true ; 
false. 

?- earlier(b, d, [a, b, c, d]). 
true ; 
false. 

憑藉獨特的處理,如果第二個參數是不是在給定列表:

?- earlier(a, not_in_list, [a, b, c, d]). 
true ; 
false. 

這是如何工作的?第一個條款說,如果X是列表的頭部,則X出現在列表的前面,而不是任何內容,由匿名變量_表示。第二個條款說,如果Y是列表的頭部,則沒有任何內容(_在第一個參數位置)在Y之前。在這種情況下,謂詞失敗並使用剪切來避免發現虛假解。第三個條款只適用於第一個和第二個條款的列表。

由於切,這個定義不是很聲明,併爲人們所預料的一些有趣的用途不起作用:

?- earlier(X, Y, Zs). 
Zs = [X|_G947] ; 
false. 

?- earlier(a, b, Zs). 
Zs = [a|_G923] ; 
false. 

?- earlier(X, Y, [a, b, c, d]). 
X = a ; 
false. 

最後一種情況,特別是可能對某些使用案例有趣。這裏是一個更聲明版本:

earlier_than(X, Y, Zs) :- 
    append(InitialPart, [X | _Rest], Zs), 
    notmember_of(Y, InitialPart). 

notmember_of(_X, []). 
notmember_of(X, [Y|Xs]) :- 
    dif(X, Y), 
    notmember_of(X, Xs). 

你可以使用這個更漂亮列舉的解決方案:

?- earlier_than(X, Y, Zs). 
Zs = [X|_G947] ; 
Zs = [_G1162, X|_G1166], 
dif(Y, _G1162) ; 
Zs = [_G1254, _G1257, X|_G1261], 
dif(Y, _G1257), 
dif(Y, _G1254) ; 
Zs = [_G1346, _G1349, _G1352, X|_G1356], 
dif(Y, _G1352), 
dif(Y, _G1349), 
dif(Y, _G1346) . 

?- earlier_than(a, b, Zs). 
Zs = [a|_G923] ; 
Zs = [_G1086, a|_G1090], 
dif(_G1086, b) ; 
Zs = [_G1169, _G1172, a|_G1176], 
dif(_G1169, b), 
dif(_G1172, b) ; 
Zs = [_G1252, _G1255, _G1258, a|_G1262], 
dif(_G1252, b), 
dif(_G1255, b), 
dif(_G1258, b) . 

?- earlier_than(X, Y, [a, b, c, d]). 
X = a ; 
X = b, 
dif(Y, a) ; 
X = c, 
dif(Y, b), 
dif(Y, a) ; 
X = d, 
dif(Y, c), 
dif(Y, b), 
dif(Y, a) ; 
false. 

就個人而言,如果規範允許,我會還新增了member(Y, Rest)earlier_than/3定義。這使事情更好:

?- earlier_than(X, Y, Zs). 
Zs = [X, Y|_G950] ; 
Zs = [X, _G949, Y|_G953] ; 
Zs = [X, _G949, _G952, Y|_G956] . 

?- earlier_than(a, b, Zs). 
Zs = [a, b|_G926] ; 
Zs = [a, _G925, b|_G929] ; 
Zs = [a, _G925, _G928, b|_G932] . 

?- earlier_than(X, Y, [a, b, c, d]). 
X = a, 
Y = b ; 
X = a, 
Y = c ; 
X = a, 
Y = d ; 
X = b, 
Y = c ; 
X = b, 
Y = d ; 
X = c, 
Y = d ; 
false. 
+0

謝謝你的解釋。 –

+0

如果您對此答案滿意,請點擊旁邊的複選標記以「接受」。 –