This predicate does not backtrack, which is the idea. Use this predicate instead of member/2 if you know you need it (to wring efficiency out of a program) and you know enough about Elem and List to be sure this predicate is appropriate.
?- findall(X, memberchk(X, [one,two,three]), Bag). Bag = [one].
?- findall(X, member(X, [one,two,three]), Bag). Bag = [one, two, three].
In fact, memberchk/2 may well be implemented as
memberchk(X, Es) :- once(member(X, Es)).
and maybe it's clearer to actually write
once(member(X, Es)) in your code.
Watch out for unexpected failure (from the paper Indexing dif/2)
?- X=2, memberchk(X, [1,2]), X=2 X=2. % expected solution ?- memberchk(X, [1,2]), X=2. false. % unexpected failure ?- member(X, [1,2]), X=2. X = 2.
Going one further: considering unbound variables as list elements
This may not be the appropriate place for this note but what if you want to consider unbound variables as elements to be manipulated, not placeholders to be instantiated?
foo a member of
[1,2,X,Y] according to member/2? There are two solutions (which partially overlap for `X
Yfoo`) and two answers:
?- member(foo,[1,2,X,Y]). X = foo ; Y = foo.
foo a member of
[1,2,X,Y] according to
memberchk/2? There is one answer:
?- memberchk(foo,[1,2,X,Y]). X = foo.
But what if you do not want to unify and consider variables as "objects" to be worked on (in fact, your are reasoning about the "list program object" itself, not what it stands for):
?- in_prefix(foo,[1,2,X,Y]). false. ?- in_prefix(Y,[1,2,X]). false. ?- in_prefix(Y,[1,2,Y]). true. ?- Y=4,in_prefix(Y,[1,2,Y]). Y = 4.
It can be done: