2011-11-27 223 views
0
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],[])。我對嗎?

回答

1

你可以看到解釋如何工作的鍵入(當然,在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而爬上一步。

1

使用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說