Checking for membership in list without instantiating anonymous variables

Hi!
Below i want to check if p(a) and p(b) are members of the list. But after the fist call to member/2, L is instantiated to p(a) so the second call to member/2 fails. Is there a way to avoid this? Ie checking for membership without changing the list that involves anonymous variables?

myList([p(_)]).

main:-
    myList(L),
    member(p(a), L),
    member(p(b), L).

Cheers/JCR

This works, but I know Jan will most likely show something that is better that I am not aware. It uses copy_term/2

other :-
    myList(L),
    copy_term(L,L1),
    member(p(a), L),
    member(p(b), L1).
?- main.
false.

?- other.
true.
1 Like

Double negation?

main:-
    myList(L),
    \+ \+ member(p(a), L),
    \+ \+ member(p(b), L).
1 Like

To this day I know that is important to know but have no clue as how or the reasoning behind it. Care to explain.

1 Like

Negation never binds variables in the negated goal. Thus, by using double negation you can verify that a goal succeeds without binding any of its variables.

4 Likes

Thanks @EricGT.

I should have explained more clearly in my original post that i don’t know how many times member/2 will be called and what the first argument of the compound p will be. So what i have is something like

myList([p(_)]).

main:-
   myList(L),
   member(p(a), L),
   member(p(b), L),
   ...,
   member(p(n), L).

Where there is an unknown number of such member/2 predicates each with p(unknownAtom).

Cheers/JC

1 Like

Thanks! This solved my problem.

In looking for more info on double negation found

forall/2

The predicate forall/2 is implemented as \+ ( Cond, \+ Action) , i.e., There is no instantiation of Cond for which Action is false. . The use of double negation implies that forall/2 does not change any variable bindings . It proves a relation. The forall/2 control structure can be used for its side-effects.