让我们追踪:
?- trace, del(5, [3,4,5,6,7], X).
Call: (7) del(5, [3, 4, 5, 6, 7], _G218) ? creep
Call: (8) 5\=3 ? creep
Exit: (8) 5\=3 ? creep
Call: (8) del(5, [4, 5, 6, 7], [_G344]) ? creep
Call: (9) 5\=4 ? creep
Exit: (9) 5\=4 ? creep
Call: (9) del(5, [5, 6, 7], [[]]) ? creep
Fail: (9) del(5, [5, 6, 7], [[]]) ? creep
Fail: (8) del(5, [4, 5, 6, 7], [_G344]) ? creep
Fail: (7) del(5, [3, 4, 5, 6, 7], _G218) ? creep
false.
所以你可以看到你的代码在到达 5 时实际上是失败的,因为它5 \= 5
是错误的。您的第一条规则永远不会匹配,因为列表中有多个项目。第二条规则在找到后“正确”重复出现5 \= 3
,5 \= 4
但由于您的任何规则都没有5 = 5
案例,因此失败发生在那里。
顺便说一下,让我们看看当列表中没有出现 5 时会发生什么:
?- trace, del(5, [3,4,6,7], X).
Call: (7) del(5, [3, 4, 6, 7], _G350) ? creep
Call: (8) 5\=3 ? creep
Exit: (8) 5\=3 ? creep
Call: (8) del(5, [4, 6, 7], [_G473]) ? creep
Call: (9) 5\=4 ? creep
Exit: (9) 5\=4 ? creep
Call: (9) del(5, [6, 7], [[]]) ? creep
Fail: (9) del(5, [6, 7], [[]]) ? creep
Fail: (8) del(5, [4, 6, 7], [_G473]) ? creep
Fail: (7) del(5, [3, 4, 6, 7], _G350) ? creep
false.
这就是为什么我之前说“正确”的原因:您的归纳案例也不正确。一方面,你有,del(Ele, T, [New])
但在上面你有del(Ele, [H|T], [H|New])
,所以你要在右边多花时间展开列表(这就是我们的跟踪[[]]
在其中的原因)。但是@false 遇到了更大的问题,即您根本不会考虑实际找到要删除的内容的情况。:) 您也不处理列表为空的情况。
不幸的是,遍历数据结构并查看每个项目将是 O(N)。另一个不幸的事实是,在函数式和声明式语言(缺少“可赋值”的语言)中,修改列表意味着复制列表的至少一部分。在 Prolog 中有更有效的方法来解决这个问题(例如,您可以使用差异列表)但它们将共享相同的基本问题。Prolog 效率是一个相当大的话题。我会告诉你不要太担心它,但它有办法很快成为你的关注点。但在这种情况下,不,没有真正更有效的方法使用破坏性更新。