Prolog - copy a piece of list

前端 未结 2 1780
借酒劲吻你
借酒劲吻你 2021-01-20 03:08

I need to duplicate list in prolog.

I have list:

L = [a(string1,value1),a(string2,value2),a(string3,value3),a(string4,value4)].

Out

相关标签:
2条回答
  • 2021-01-20 03:25

    It is uncommon to use a structure a/2 for this purpose. More frequently, (-)/2 is used for this. Key-Value is called a (key-value) pair.

    Also the name itself is not very self-revealing. This is no copy at all. Instead, start with a name for the first argument, and then a name for the second. Lets try: list_list/2. The name is a bit too general, so maybe apairs_keys/2.

    ?- apairs_keys([a(string1,value1),a(string2,value2)], [string1, string2]).
    

    Here are some definitions for that:

    apairs_keys([], []).
    apairs_keys([a(K,_)|As], [K|Ks]) :-
       apairs_keys(As, Ks).
    

    Or, rather using maplist:

    apair_key(a(K,_),K).
    
    ?- maplist(apair_key, As, Ks).
    

    Or, using lambdas:

    ?- maplist(\a(K,_)^K^true, As, Ks).
    

    Declarative debugging techniques

    Maybe you also want to understand how you can quite rapidly localize the error in your original program. For this purpose, start with the problematic program and query:

    copy2([],[]).
    copy2([H|L1],[K|L2]) :-
       member(f(K,_),H),
       copy2(L1,L2).
    
    | ?- copy2([a(string1,value1),a(string2,value2),a(string3,value3),a(string4,value4)], [string1, string2, string3, string4]).
    no
    

    Now, generalize the query. That is, replace terms by fresh new variables:

    | ?- copy2([a(string1,value1),a(string2,value2),a(string3,value3),a(string4,value4)], [A, B, C, D]).
    no
    | ?- copy2([a(string1,value1),a(string2,value2),a(string3,value3),a(string4,value4)], L).
    no
    | ?- copy2([a(string1,value1),B,C,D], L).
    no
    | ?- copy2([a(string1,value1)|J], L).
    no
    | ?- copy2([a(S,V)|J], L).
    no
    | ?- copy2([A|J], L).
    A = [f(_A,_B)|_C],
    L = [_A|_D] ? 
    yes
    

    So we hit bottom... It seems Prolog does not like a term a/2 as first argument.

    Now, add

    :- op(950,fx, *).
    
    *_.
    

    to your program. It is kind of a simplistic debugger. And generalize the program:

        copy2([],[]).
        copy2([H|L1],[K|L2]) :-
           member(f(K,_),H),
           * copy2(L1,L2).
    

    Member only succeeds with H being of the form [_|_]. But we expect it to be a(_,_).

    0 讨论(0)
  • 2021-01-20 03:45

    pattern matching is used to decompose arguments: you can do

    copy([],[]).
    copy([a(H,_)|L1],[H|L2]) :- copy(L1,L2).
    
    0 讨论(0)
提交回复
热议问题