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.
精彩评论