简单的Prolog从列表中删除

时间:2011-06-22 14:25:21

标签: 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.)然后回溯为我提供了列表的所有其他变体,其中一些或没有X实例被删除。

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

2 个答案:

答案 0 :(得分:6)

当您使用(==)/2进行比较时,您需要在第三条规则中采用相反的方法,即(\==)/2。另一方面,这样的定义不再是纯粹的关系。要查看此内容,请考虑deleteall([X],Y,Zs), X = Y.

对于纯粹的关系,我们需要(=)/2dif/2。许多Prolog如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).

查看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).

答案 1 :(得分:2)

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

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