2011-11-27 116 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说