More determinism for `memberd/2`?

后端 未结 3 1842
予麋鹿
予麋鹿 2020-12-20 11:59

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.         


        
3条回答
  •  既然无缘
    2020-12-20 12:23

    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.
    

    Edit

    The implementation of memberd_new/2 presented here is deprecated.

    I recommend using the newer implementation shown in this answer.

提交回复
热议问题