开发者

Prolog remove function - almost working

The following predicate is remove(L,X,R), where L is a list, X is an element to remove from the list. The code returns the correct list, however it always also returns false afterwards.

I can't find the place where two of the rules can be applied during runtime.

remove([],X,[]) :- !. 
remove([X|T],X,L1) :- remove(T,X,L1). 
remove([H|T],X,[H|L1]) :- \+(X==H), remove(T,X,L1). 

Sample query wi开发者_如何学编程th expected result:

?- remove([1,2,3,4],3,R).
R = [1, 2, 4] ; 
false.


If your Prolog system supports clpfd, you can preserve logical-purity by proceeding as follows. Using meta-predicate tfilter/3 and reified inequality predicate dif/3, we can write:

remove(Xs0,E,Xs) :- tfilter(dif(E),Xs0,Xs).

Quick check if it works:

?- tfilter(dif(3),[1,2,3,4],Xs).
Xs = [1,2,4].                     % succeeds deterministically

tfilter/3 and dif/3 are monotone, so we get sound answers, even for general queries:

?- remove([A,B,C],3,Xs).
Xs = [     ],     A=3 ,     B=3 ,     C=3  ;
Xs = [    C],     A=3 ,     B=3 , dif(C,3) ;
Xs = [  B  ],     A=3 , dif(B,3),     C=3  ;
Xs = [  B,C],     A=3 , dif(B,3), dif(C,3) ;
Xs = [A    ], dif(A,3),     B=3 ,     C=3  ;
Xs = [A,  C], dif(A,3),     B=3 , dif(C,3) ;
Xs = [A,B  ], dif(A,3), dif(B,3),     C=3  ;
Xs = [A,B,C], dif(A,3), dif(B,3), dif(C,3) ;
false.


http://www.cs.bris.ac.uk/Teaching/Resources/COMS30106/labs/tracer.html - SWI-prolog has tracing/debugging mode. In my opinion, cmd-line debugger is better than the visual one.

EDIT:

remove([],X,[]) :- !. 
remove([X|T],X,L1) :- !, remove(T,X,L1).          <-- cut was added
remove([H|T],X,[H|L1]) :- remove(T,X,L1).         <-- condition was deleted

The above code should be allright. No warranties though.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜