More determinism for `memberd/2`?

后端 未结 3 1848
予麋鹿
予麋鹿 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:19

    In this answer we compare three different list-membership predicates:

    • member/2, a builtin predicate, as implemented in SWI-Prolog.
    • memberd/2, as defined by the OP:

      memberd(E,[X|Xs]) :-
         if_(E=X, true, memberd(E,Xs)).
      
    • memberd_new/2, a proposed alternative which is defined like this:

      memberd_new(E,[X|Xs]) :-
         (  Xs \= [_|_]
         -> E=X
         ;  if_(E=X, true, memberd_new(E,Xs))
         ).
      

    Let's go!

    First, some ground queries:

    ?- member(b,[a,b]).
    true.
    ?- memberd(b,[a,b]).
    true.
    ?- memberd_new(b,[a,b]).
    true.
    
    ?- member(a,[a,a]).
    true ; true.                        % BAD
    ?- memberd(a,[a,a]).
    true.
    ?- memberd_new(a,[a,a]).
    true.
    
    ?- member(a,[a,b]).
    true ; false.                       % BAD 
    ?- memberd(a,[a,b]).
    true.
    ?- memberd_new(a,[a,b]).
    true.
    

    Next, some queries having multiple distinct solutions:

    ?- member(X,[a,b]).
    X = a ; X = b.
    ?- memberd(X,[a,b]).
    X = a ; X = b ; false.              % BAD
    ?- memberd_new(X,[a,b]).
    X = a ; X = b.
    

    Next, a test-case suggested in a comment to a previous answer which broke the version of memberd_new/2 presented earlier.

    ?- member(a,[a|nonlist]).
    true.
    ?- memberd(a,[a|nonlist]).
    true.
    ?- memberd_new(a,[a|nonlist]).
    true.                               % IMPROVED
    

    A variation of above test-case:

    ?- member(X,[a|nonlist]).
    X = a.
    ?- memberd(X,[a|nonlist]).
    X = a ; false.                      % BAD
    ?- memberd_new(X,[a|nonlist]).
    X = a.                              % IMPROVED
    

    Last, some non-terminating queries:

    ?- member(1,Xs).
      Xs =          [1|_A]
    ; Xs =       [_A,1|_B]
    ; Xs =    [_A,_B,1|_C]
    ; Xs = [_A,_B,_C,1|_D]
    ...
    
    ?- memberd(1,Xs).
      Xs =          [1|_A]
    ; Xs =       [_A,1|_B], dif(_A,1)
    ; Xs =    [_A,_B,1|_C], dif(_A,1), dif(_B,1)
    ; Xs = [_A,_B,_C,1|_D], dif(_A,1), dif(_B,1), dif(_C,1) 
    ...
    
    ?- memberd_new(1,Xs).
      Xs =          [1|_A]
    ; Xs =       [_A,1|_B], dif(_A,1)
    ; Xs =    [_A,_B,1|_C], dif(_A,1), dif(_B,1)
    ; Xs = [_A,_B,_C,1|_D], dif(_A,1), dif(_B,1), dif(_C,1)
    ...
    

提交回复
热议问题