从列表中删除元素

时间:2011-11-27 18:13:53

标签: prolog

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],[])。我是对的吗?

2 个答案:

答案 0 :(得分:1)

你可以通过键入来看到解释器是如何工作的(至少在swi-pl中,在其他实现中应该类似):

?- trace, del(c, [a,b,c],X).
顺便说一下,你当然忘了包括一行如下:

del(_, [], []).

否则算法不会初始化结果列表 然后它是非常基本的:如果列表的第一个元素与您要删除的元素一致,则跳过它,否则,将其包含在结果列表中。

在这里基本上,它会像那样工作:
del(c,[a,b,c],X)=> c不能与a统一,所以我们将在最后构建列表时包含一个 del(c,[b,c],X)=> c不能与b统一,所以在从最后构建列表时我们将包括b del(c,[c],X)=> c可以与c统一,所以从最后构造列表时我们不会包含c del(c,[],X)=>当X = []时,[]为真,所以让我们说X = []现在让我们通过爬上递归来构造我们的结果列表:
爬升一步时X = [],因为不包括c 当爬上一步因为包含b时,X = [b] 由于包含a,因此当爬上一步时X = [a,b]。

答案 1 :(得分: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] .

在每个“转弯”prolog将检查第一个元素是否是我们想要删除的元素。 如果是的话,我们就完成了。 否则,我们保持头部并递归调用del / 3作为列表的尾部

我们是否应该考虑如果元素不在给定列表中会发生什么是另一回事;我们可能希望谓词在这种情况下失败,我们可能想要返回整个列表然后我们应该添加del(_, [], []).作为mog说