Search code examples
listprologprolog-diflogical-purity

Prolog: remove member of list with non-instantiated values


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???


Solution

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