I know this question has been asked already, but I just want to ask about my specific implementation. I'm writing this function just to practice Prolog and better understand Prolog. Here's what I have:
del(Ele, [H], [H]) :- Ele \= H.
del(Ele, [H|T], [H|New]) :-
Ele \= H,
del(Ele, T, [New]).
The idea is that I will add an element to a new list called New
if the element I want to delete is not equal to H
. From what I understand, my code isn't working because my code stops when I reach an element where Ele \= H
. Any ideas how to fix this?
For example, del(5, [3,4,5,6,7], X)
will return false.
Also, are there any better solutions? It seems like a bad solution to keep adding every element in a list to a new list, since this would be slow for a large list. I'd rather just keep the elements currently in the list, find element(s) that match Ele
, remove that element, and then return the list.
You have described some cases where del/3
should hold. But these are only cases where Ele
is not equal/unifiable to the elements in the list. There are several things missing:
What about the empty list?
What, if Ele
is equal to the element?
So you need to add further clauses. (Later you might also remove some, for reasons of redundancy).
If you are using SWI, B, SICStus, or YAP, consider to use dif/2
in place of (\=)/2
. prolog-dif
Here is the reason why dif/2
is so helpful in this case. With dif/2
you would have a pure monotonic program. And you could try it out directly:
?- del(5, [3,4,5,6,7], X). false.
The same problem you had. Let me just restate what the problem is: You expect that something should hold, but it does not. So the relation is too narrowly defined. If I generalize the query, I might get a better answer. Try del(E, [3,4,5,6,7], X).
but again the same false
. So I'll try an even more general query:
?- del(E, Xs, Ys). Xs = Ys, Ys = [_A], dif(E,_A) ; ... .
Looks perfect to me! Maybe another answer:
?- del(E, Xs, Ys). Xs = Ys, Ys = [_A], dif(E,_A) ; Xs = [_A,_B], Ys = [_A|_B], dif(E,_B), dif(E,_A) ; ... .
Now we got an incorrect answer. I will instantiate it a bit to make it better readable:
?- del(e, [a,b], Ys). Ys = [a|b] ; false.
This answer is clearly incorrect because [a|b]
is not a list. And, it's probably the smallest incorrect answer...
What I want to show you by this is that you can most often locate problems without going through it step-by-step. Step-by-step debugging does not even work in imperative languages once you get a more complex control flow (like concurrency) ; and it does not scale at all in Prolog.