del/3
(1) del(S,[P],[P]).
(2) del(S,[S],[]).
(3) del(S,[H1,H2|T],L2) :- H1 = S, del([H2|T],L2).
(4) del(S,[H1,H2|T],[H1,T2]) :- H1 \= S, del([H2|T],T2).
(1)該規則表示,列表[P]
是列表[P]
與元件S
除去。此規則的問題是S
和P
可能是相同的值,因此該規則並非總是如此。如果你想這是真的所有的時間(是一個有效的規則),你需要規定S
和P
不能被實例化,以相同的值:
del(S, [P], [P]) :- S \= P.
這是假設,我們甚至需要這個規則,但我們暫時將它留在這裏,因爲在這個新的狀態下,這是正確的。
(2)這條規則說[]
是列表[S]
與元素S
去除。那是真實的。
(3)這條規則說L2
是,如果H1
和S
是統一的,L2
是[H2|T]
與S
刪除刪除列表[H1,H2|T]
與S
。但是,缺少一個參數。您有del([H2|T], L2)
,但del/3
被定義爲需要3個參數。我們假設你的意思是S
是第一個參數(S
仍然是什麼被刪除),所以del(S, [H2|T], L2)
。新修理的規則似乎是合乎邏輯的。
(4)這條規則說,* [H1,T2]
是列表[H1,H2|T]
與如果H1
刪除的元素S
不unifiable與S
和T2
是列表[H2|T]
與中移除的元素S
。這與#3有同樣的問題,del/3
缺失的參數,我們將再次假設爲S
,使其成爲del(S, [H2|T], T2)
。另一個問題是,您有[H1,T2]
這是一個只有兩個元素的列表:H1
和T2
。另一個錯字。這應該是[H1|T2]
。所以修好的規則現在似乎有意義。
只是修復這些粗心的錯誤導致你的謂詞幾乎可以工作!當第一個參數被實例化時,它會產生正確的結果:
| ?- del(a, [a,b,c,a,d,a], L).
L = [b,c,d] ? a
no
此外,它可以清理一下。 H2
沒有真正用於第3和第4章。在第3個子句中,可以在謂詞的頭部實例化S
和H1
。因此,這兩個變爲:
(3) del(S, [S|T], L2) :- del(S, T, L2).
(4) del(S, [H|T], [H|T2]) :- H \= S, del(S, T, T2).
謂詞在列表中失敗爲空。我不確定這是否是故意的,但是您可能會認爲del(X, [], [])
應該爲真(當您從空列表中刪除某個元素時,會生成一個空列表)。如果我們有這樣的規則:
(1a) del(_, [], []).
我們現在可以擺脫規則(1)和(2),因爲(3)和(4)將照顧他們和遞歸下降到規則(1A)。
此外,該規則還未能在這種情況下:
| ?- del(X, [a,b,c], [a,c]).
no
這將是很好,如果這打嗝了,X = b
。問題是在條款(4)中,我們檢查H \= S
這意味着H
和S
不可統一。如果S
是一個變量,則此表達式對我們有效,因爲H \= S
將始終失敗(因爲S
確實可以統一爲H
)。所以我們用dif(H,S)
替換它來檢查這些條款是否相同。 某些序言不提供dif/2
,在這種情況下,您可以用\==
替代此解決方案(H \== S
)。我們得到的規則集:
(1) del(_, [], []).
(2) del(S, [S|T], L2) :- del(S, T, L2).
(3) del(S, [H|T], [H|T2]) :- dif(H, S), del(S, T, T2).
讓我們「重讀」的規則:
- 從空的列表中移除所有元素是空列表。
- 列表
[S|T]
除去了元件S
是列表L2
如果L2
是列表T
移除了元件S
。
- 列表
[H|T2]
是列表[H|T]
移除了元件S
如果S
不同於H
和T2
是列表T
移除了元件S
。
這看起來簡單得多,雖然只是一些簡單的回頭離開原來的。現在會產生這樣的結果,這是很好的:
| ?- del1(X, [a,b,c,b,d], [a,c,d]).
X = b ? ;
(1 ms) no
考試change/2
(1) change([],[]).
(2) change([H1,H2|T],L) :- H1 = 2, append([2],L), change([H2|T],L).
(3) change([H1,H2|T],L) :- H1 \= 2, append(H1,L), change([H2|T],L).
(1)這條規則是說,如果我們改變所有的2公司在空列表,我們得到的空的清單。聽起來不錯。
(2)這條規則說,如果我把名單[H1,H2|T]
,我改變了2對4的,我得到L
如果H1
是2和我追加L
到[2]
(這是自[2]
總是會失敗不變量 - 見爲append/2
和append/3
在線文檔!append/2
是追加列表的列表,例如)和L
是[H2|T]
2的改變爲4的。這已經沒有任何邏輯意義了。如果我將2更改爲4,我爲什麼要追加[2]
?我們要失去append
和簡單統一L
與[4|T2]
其中T2
是[H2|T]
其2的改變爲4的。或換句話說:
(2) change([H1,H2|T], L) :- H1 = 2, L = [4|T2], change([H2|T], T2).
這可以進一步簡化使用在上面的子句的頭部合併統一的方法。另外請注意,我們沒有真正用於在此處顯示H2
。所以[H2|T]
可以只是一個T
:
(2) change([2|T], [4|T2]) :- change(T, T2).
所以我們使用的4而不是2,如果有一個2,然後處理尾巴。
(3)此規則與append/2
查詢具有相同的問題(2)。我們可以按照我們與規則(2)做了同樣的模式,並解決非等檢查:
(3) change([H|T], [H|T2]) :- H \== 2, change(T, T2).
所以我們只是結轉的元素H
如果它不是一個2,然後處理尾巴。完整的change
謂詞的樣子:
(1) change([], []).
(2) change([2|T], [4|T2]) :- change(T, T2).
(3) change([H|T], [H|T2]) :- H \== 2, change(T, T2).
李自成的規則,看到他們作出合乎邏輯的意義:
- 變更2對4層的在空列表是空列表。
- 變更2對4名在列表中
[2|T]
是列表[4|T2]
如果T2
是列表T
與2的改變爲4的。
- 變更2對4名在列表中
[H|T]
是列表[H|T2]
如果H
不2
和T2
是列表T
與2的改變爲4的。
太謝謝你了。這非常有幫助。我很欣賞一步一步以及如何閱讀條款。現在對我來說更有意義。 – user3342236
@ user3342236我很高興你發現它有幫助。 :) – lurker