prolog - 从列表中删除简单的 Prolog

标签 prolog prolog-dif

(这不是一个类(class)作业问题。只是我自己的个人学习。)

我正在尝试在 Prolog 中进行练习以从列表中删除元素。这是我的代码:

deleteall([],X,[]).
deleteall([H|T],X,Result) :- 
    H==X,
    deleteall(T,X,Result).
deleteall([H|T],X,[H|Result]) :- deleteall(T,X,Result).

当我测试它时,我首先得到了一个很好的答案(即删除了所有的 X。)但是,回溯为我提供了列表的所有其他变体,其中一些 X 的实例被删除了,或者没有。

为什么会这样?为什么 H==X 的情况会落到最后一个子句?

最佳答案

当您使用时 (==)/2为了进行比较,您需要在第三条规则中使用相反的规则,即 (\==)/2 .另一方面,这样的定义不再是纯粹的关系。要看到这一点,请考虑 deleteall([X],Y,Zs), X = Y.
对于纯关系,我们需要 (=)/2dif/2 . SWI、YAP、B、SICStus 等许多 Prolog 提供 dif/2 .

deleteall([],X,[]).
deleteall([H|T],X,Result) :- 
    H=X,
    deleteall(T,X,Result).
deleteall([H|T],X,[H|Result]) :-
    dif(H,X),
    deleteall(T,X,Result).

查看 deleteall([X,Y],Z,Xs) 的答案!

编辑(四年后):

更高效,但同样纯粹,可以使用 if_/3 来写和 (=)/3 :
deleteall([], _X, []).
deleteall([E|Es], X, Ys0) :-
   if_( E = X, Ys0 = Ys, Ys0 = [E|Ys] ),
   deleteall(Es, X, Ys).

关于prolog - 从列表中删除简单的 Prolog,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6441527/

相关文章:

prolog - 列表列表中的组合 Prolog

prolog - 处理序言上下文无关语法

prolog - 猜猜 Prolog 中的类似游戏

prolog - 如何在序言中加入规则并打印输出

prolog - 序言中的递归引用

prolog - GNU Prolog `delete/3` 谓词中的异常?

path - 尝试获取给定路径的成本

list - 如何实现 not_all_equal/1 谓词

prolog - 解决 Prolog 中的文本逻辑难题 - 查找生日和月份

list - 字符串列表的最长公共(public)前缀 (LCP)