Declarative uses of memberchk/2

前端 未结 3 911
逝去的感伤
逝去的感伤 2020-12-10 12:09

memberchk/2 is a commonly defined predicate that is defined in terms of member/2 like so:

memberchk(X, Xs) :-
   once(member(X, Xs)         


        
3条回答
  •  星月不相逢
    2020-12-10 12:27

    Here is a well-known example use of member/2 that cannot be represented by memberd/2: bridge.pl the bridge scheduling problem given by Pascal Van Hentenryck.

    In the setup phase member/2 is used:

    setup(K,Ende,Disj):-
        jobs(L),
        make_vars(L,K),
        member([stop,_,Ende],K),
        ....
    

    So here, effectively the first element in the three-element list is used to select a particular task whereas memberd/2 uses the entire element for comparison. As a consequence this setup/3 leaves open a lot of choicepoints (actually, 219). Some (like SICStus) use memberchk/2 in that situation, thereby risking non-monotonicity.

    Using the following pure replacement, all choicepoints are avoided.

    member3l([N,D,A], Plan) :-
       tmember(l3_t(N,D,A),  Plan).
    
    l3_t(N,D,A, X, T) :-
       X = [Ni|_],
       if_(N = Ni, ( X=[N,D,A], T = true ), T = false ).
    
    tmember(P_2, [X|Xs]) :-
       if_( call(P_2, X), true, tmember(P_2, Xs) ).
    

    Alternatively using library(lambda):

    member3li([N,Nd,Na], Plan) :-
       tmember([N,Nd,Na]+\X^T^
           (  X=[Nk|_],
              if_( Nk = N, ( X=[N,Nd,Na], T = true ), T = false ) ),
          Plan).
    

    Other uses of tmember/2:

    old_member(X, Xs) :-
       tmember( X+\E^T^( X = E, T = true ; T = false ), Xs).
    
    old_memberd(X, Xs) :-
       tmember(=(X), Xs).
    

    Here is a more compact representation:

    member3l([N,D,A], Plan) :-
       tmember({N,D,A}+\[Ni,Di,Ai]^cond_t(N = Ni, [D,A] = [Di,Ai] ), Plan).
    

    Using library(lambda)and cond_t/3:

    cond_t(If_1, Then_0, T) :-
       if_(If_1, ( Then_0, T = true ), T = false ).
    

提交回复
热议问题