Valentim Santos
Valentim Santos

Reputation: 13

Is there a function that checks if a variable is a member of a list without unifying it?

I want to implement a predicate in my cod that finds all the lists that contain a certain element, in my case, that element is a variable, P3 for example. The problem is that using the predicate member doesn't work because it keeps unifying the variable with the elements of the list:

?- member(P3, [P1,P3]). P3 = P1 ; true.

I want it to return True because P3 is a member of the list and not because P1 is. Is there a way for me to check if the variable P3 is a member of a list without unifying it? Thanks.

Upvotes: 1

Views: 108

Answers (2)

rajashekar
rajashekar

Reputation: 3765

There is (==)/2 which does what you require.

@Term1 == @Term2
True if Term1 is equivalent to Term2. A variable is only identical to a sharing variable.

?- X == Y.
false.

?- X=a, Y=b, X == Y.
false.

?- X=a, Y=a, X == Y.
X = Y, Y = a.

So you can implement it as

membersame(X, [A|_]) :-
    X == A.
membersame(X, [_|Rest]) :-
    membersame(X, Rest).

Or you can also use member/2 for implicit iteration over the list and use (==)/2 for restriction (thanks @TA_intern).

membersame(X, Xs) :-
    member(Y, Xs), X == Y.

Examples:

?- membersame(X, [A, B, C, X, a, b, c]).
true ;
false.

?- membersame(X, [A, B, C, a, b, c]).
false.

Upvotes: 1

slago
slago

Reputation: 5519

In Prolog, a variable can be unified with a value only once. Consequently, if variable V can be unified with this and variable Wcan be unified with that, then those variables are distinct (otherwise, they are the same variable).

samevar(V, W) :- var(V), var(W), not((V=this, W=that)).

Here are some examples:

?- samevar(A,B).
false.

?- samevar(A,A).
true.

Using samevar/2, we can define the following predicate:

varmember(V, [W|_]) :- samevar(V, W).
varmember(V, [_|T]) :- varmember(V, T).

Here are some examples:

?- varmember(a, [V1, a, V3, V4, V5]).
false.

?- varmember(V2, [V1, V3, V4, V5]).
false.

?- varmember(V2, [V1, V2, V3, V4, V5]).
true ;
false.

?- varmember(V2, [V1, V2, V3, V2, V4, V5]).
true ;
true ;
false.

?- varmember(V2, [V1, V2, V3, V2, V4, V2, V5]).
true ;
true ;
true ;
false.

?- varmember(V2, [this, V2, that, V2, V3, V4, V5]).
true ;
true ;
false.

Upvotes: 0

Related Questions