简单的Prolog从列表中删除

简单的Prolog从列表中删除,prolog,prolog-dif,Prolog,Prolog Dif,(这不是一个课程问题,只是我个人的学习。) 我试图在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),但随后回溯为我提供了列表的所有其他变体

(这不是一个课程问题,只是我个人的学习。)

我试图在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的情况会出现在最后一个子句中?

最后一个子句说,当从列表中删除
X
时,head元素可能会保留(与其值无关)。Prolog可以在其认为合适的任何时候使用该子句,而不依赖于前一子句中的条件是否正确,如果另一个子句失败,或者如果您指示它这样做(例如,通过在顶层发出
,以获得下一个解决方案)。如果添加head元素可能不等于
X
的条件,则它应该可以工作

编辑:删除了我最初打开时使用的错误断言。

当您使用
(==)/2
进行比较时,您需要在第三条规则中使用相反的断言,即
(\==)/2
。另一方面,这样的定义不再是纯粹的关系。要看到这一点,请考虑<代码> DeleTALALL([X],Y,ZS),X= Y.< /代码>

对于纯关系,我们需要
(=)/2
dif/2
。许多开场白,如SWI、YAP、B、SICStus,都提供了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).
查看
删除所有([X,Y],Z,Xs)
的答案

编辑(四年后):

效率更高,但同样纯粹,可以使用和
(=)/3

deleteall([], _X, []).
deleteall([E|Es], X, Ys0) :-
   if_( E = X, Ys0 = Ys, Ys0 = [E|Ys] ),
   deleteall(Es, X, Ys).

哦出于某种原因,我认为是这样的。(也就是说,清单算在内了。)这就解释了我面临的许多问题。Prolog子句是按照从左到右、自上而下的顺序执行的,尽管解释器在失败时可能会返回到以下子句中。子句的顺序并不是完全无序的。它们是按固定顺序考虑的。但你的观点是正确的:只要没有