Many systems provide a pure and efficient implementation of member/2. In particular, no choice point is left open for:
?- member(b,[a,b]). true. whereas, a naive implementation of member/2 produces rather:
?- member(b,[a,b]). true ; false. which is certainly correct from a declarative viewpoint, but less efficient.
On the other hand, there are some technical problems with member/2. It permits redundant solutions, like in:
?- member(a,[a,a]). true ; true. memberd/2 solves this problem using if_/3 and (=)/3.
memberd(E, [X|Xs]) :- if_(E = X, true, memberd(E, Xs)). ?- memberd(a,[a,a]). true. Unfortunately, this definition leaves choice points open again - producing ; false ("leftover choicepoints") in situations where member does not:
?- memberd(X,[a,b]). X = a ; X = b ; false. % BAD - to be avoided! ?- member(X,[a,b]). X = a ; X = b. So my question: Is there a definition of memberd/2 that avoids the choice point as this one above?
First, we rename memberd to memberd_old for the sake of clarity.
Then, we implement memberd_new/2, which uses lagging and 1st argument indexing to prevent the creation of the useless choicepoint at the end of the list.
memberd_new(E,[X|Xs]) :- memberd_new_aux(Xs,X,E). % auxiliary predicate to enable first argument indexing memberd_new_aux([],E,E). memberd_new_aux([X1|Xs],X0,E) :- if_(E=X0, true, memberd_new_aux(Xs,X1,E)). Let's compare member/2 (SWI-Prolog builtin predicate), memberd_old/2, and memberd_new/2!
First, a ground query:
?- member(a,[a,a]). true ; true. % BAD! ?- memberd_old(a,[a,a]). true. ?- memberd_new(a,[a,a]). true. Next, another ground query:
?- member(a,[a,b]). true ; % BAD! false. ?- memberd_old(a,[a,b]). true. ?- memberd_new(a,[a,b]). true. Now, a query having multiple distinct solutions:
?- member(X,[a,b]). X = a ; X = b. ?- memberd_old(X,[a,b]). X = a ; X = b ; % BAD! false. ?- memberd_new(X,[a,b]). X = a ; X = b. The implementation of memberd_new/2 presented here is deprecated.
I recommend using the newer implementation shown in this answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With