views:

207

answers:

1

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

Output:

remove([1,2,3,4], 3, R). 
R = [1, 2, 4] ; 
false.
+1  A: 

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.

MartyIX
Thank you - I'll use it to debug and find my problem.
Adrian
Well, you get the result as you wrote above because:when the prolog recurses to the element 3 it has two choices: use second predicate or use third predicate. Usage of the second predicate leads to the result R = [1, 2, 4] ; ... which is what you want. But usage of the third predicate (this predicate is used when you want more results from SWI-prolog) leads to the false result - why? Because the unification on the head of predicate is used (and therefore H and X has the same value 3) and then the condition \+(X==H) is checked which fails => therefore result "false.".
MartyIX
Thank you! Thats excellent! I wasn't aware that you are able to cut on a line with other calls! I have tested your code and it works fabulously.
Adrian