del(X,[X|Reszta],Reszta).
del(X,[Y|Ogon],[Y|Reszta]) :- del(X,Ogon,Reszta).
我不明白這段代碼。如果我問:從列表中刪除元素
?- del(c, [a,b,c],X).
編譯器會去第二行,他將觸發一個遞歸循環del(x,[b,c],[])
。我對嗎?
del(X,[X|Reszta],Reszta).
del(X,[Y|Ogon],[Y|Reszta]) :- del(X,Ogon,Reszta).
我不明白這段代碼。如果我問:從列表中刪除元素
?- del(c, [a,b,c],X).
編譯器會去第二行,他將觸發一個遞歸循環del(x,[b,c],[])
。我對嗎?
你可以看到解釋如何工作的鍵入(當然,在SWI-PL至少,應該在其他實現類似的東西):
?- trace, del(c, [a,b,c],X).
順便說一句,你肯定忘了,包括線路,如:
del(_, [], []).
否則算法不會初始化結果列表。
然後它非常基本:如果列表的第一個元素與要刪除的元素一致,則跳過它,否則將其包含在結果列表中。
所以basicly在這裏,它會像那:
德爾(C,[A,B,C],X)=> C不能與統一,所以我們將構建從列表中時,包括結束。 (c,[b,c],X)=> c不能與b統一,因此從末尾構造列表時我們將包含b。 (c,[c],X)=> c可以與c統一,所以從末尾構造列表時我們不會包含c。
當X = []時,del(c,[],X)=> []是真的,所以我們假設X = [],現在我們通過爬上遞歸構造我們的結果列表:
X = []因爲c不包括在內,因此只需一步。
X = [b]因爲包括b而爬上一步。
X = [a,b]因爲包含a而爬上一步。
使用trace/0來看看會發生什麼。在這種情況下:
4 ?- trace.
true.
[trace] 4 ?- del(c,[a,b,c],X).
Call: (6) del(c, [a, b, c], _G531) ? creep
Call: (7) del(c, [b, c], _G607) ? creep
Call: (8) del(c, [c], _G610) ? creep
Exit: (8) del(c, [c], []) ? creep
Exit: (7) del(c, [b, c], [b]) ? creep
Exit: (6) del(c, [a, b, c], [a, b]) ? creep
X = [a, b] .
在每個「turn」prolog將檢查第一個元素是否是我們想要刪除的元素。如果是,我們就完成了。 否則,我們保持頭部遞歸調用列表尾部的del/3
我們是否應該考慮如果元素不在給定列表中會發生什麼是另一回事;我們可能希望謂詞在這種情況下失敗,我們可能想要返回整個列表,然後我們應該添加del(_, [], []).
,因爲mog說