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