Reputation: 111
I've been working with this for a while. I came to a solution for a typical prolog exercice, to remove all the ocurrences of an element in a list... But I've been trying to figure out how to remove them if there are lists inside the list.
This is the furthes I've come with:
delete(X, Y, Lres) :-
delete(X, Y, [], Lres).
delete([], Y, Ac, Lres):-
Lres = Ac.
delete([H|T], Y, Ac, Lres):-
is_list(H),
delete(H, Y, Ac, Lres),
delete(T, Y, Lres, Lres).
delete([H|T], Y, Ac, Lres):-
H = Y,
delete(T, Y, Ac, Lres).
delete([H|T], Y, Ac, Lres):-
delete(T, Y, [H|Ac], Lres).
Doing this call:
[trace] 23 ?- delete([1, 2, [3, 1,3], 4, 5, 3], 2, LRes).
It fails with this:
Call: (13) delete([], 2, [3, 5, 4, 3, 1, 3, 1], [3, 1, 3, 1]) ? creep
Call: (14) [3, 1, 3, 1]=[3, 5, 4, 3, 1, 3, 1] ? creep
Fail: (14) [3, 1, 3, 1]=[3, 5, 4, 3, 1, 3, 1] ?
If there a way to change the value of a variable in prolog?
I explain myself:
When I wrote this:
delete([], Y, Ac, Lres):-
Lres = Ac.
I thought that the value of Lres would be replaced by Ac, but indeed it is comparing Lres with Ac which is false, but I don't get why it does work when Lres is empty. From the same call here is the trace for that case:
Call: (13) delete([], 2, [3, 1, 3, 1], _G1276) ? creep
Call: (14) _G1276=[3, 1, 3, 1] ? creep
Exit: (14) [3, 1, 3, 1]=[3, 1, 3, 1] ? creep
I've been thinking a while in this and I don't see any other way to do this!
Upvotes: 1
Views: 148
Reputation: 60034
I think you're doing more complicated than needed: why do you introduce an additional argument? Plain matching seems to lead to a simple solution:
delete([], _, []).
delete([E|Es], E, Rs) :-
!, delete(Es, E, Rs).
delete([L|Es], E, [D|Rs]) :-
is_list(L),
!, delete(L, E, D),
delete(Es, E, Rs).
delete([N|Es], E, [N|Rs]) :-
delete(Es, E, Rs).
and this yields
?- delete([1, 2, [3, 1, 2, 3], 4, 5, 3], 2, LRes).
LRes = [1, [3, 1, 3], 4, 5, 3].
Upvotes: 2