2

I want remove all appearences of an element on a list, similar to this, but in my case, the list may have non-instantiated variables. For example:

delMember(z, [A,B,A,z], L).
L = [A, B, A];
false.

and

delMember(A, [A, B, A, z], L).
L = [B,z];
false.

I tried defining delMember as the following:

delMember(_, [], []).
delMember(X, [X|Xs], Y) :- delMember(X, Xs, Y).
delMember(X, [T|Xs], [T|Y]) :- X \== T, delMember(X, Xs, Y).

With this definition, the last result I get is correct but it's still trying to instantiate the variables before that.

?- delMember(A, [A,B,A,z], R).
A = B, B = z,
R = [] ;
A = B,
R = [z] ;
A = z,
R = [B] ;
R = [B, z] ;

any ideas???

Community
  • 1
  • 1
lithiium
  • 647
  • 8
  • 25
  • 2
    The unification is occurring in your second clause: `delMember(X, [X|Xs], Y) :- delMember(X, Xs, Y).`, which will unify the first argument with the head of the list in the second argument if they are unifiable. Since you are trying to avoid that, you need to use `==` there as well: `delMember(X, [Y|Xs], R) :- X == Y, delMember(X, Xs, R).` – lurker Jun 05 '16 at 02:58
  • Thank you @lurker ! That was exactly what I needed. If you want to put an answer with that, I will be happy to accept it. – lithiium Jun 05 '16 at 03:55

1 Answers1

1

If you look at your second predicate clause:

delMember(X, [X|Xs], Y) :- delMember(X, Xs, Y).

Unification is occurring with the X in the first and second arguments. This leads to the results you are observing when you do your query. You need to apply the same operator as you did in your third clause. So your complete predicate (with some slightly changed variable names to be more conventional) would look like:

delMember(_, [], []).
delMember(X, [X1|Xs], Ys) :- X == X1, delMember(X, Xs, Ys).
delMember(X, [X1|Xs], [X1|Ys]) :- X \== X1, delMember(X, Xs, Ys).
lurker
  • 56,987
  • 9
  • 69
  • 103