简体   繁体   中英

Prolog - copy a piece of list

I need to duplicate list in prolog.

I have list:

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

Output will be: L = [string1, string2, string3, string4] .

How can I do this?

I can copy whole list by code:

copy([],[]).
copy([H|L1],[H|L2]) :- copy(L1,L2).

I have tried something like:

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

But it does not work properly.

But I need only strings from my original list. Can anyone help?

pattern matching is used to decompose arguments: you can do

copy([],[]).
copy([a(H,_)|L1],[H|L2]) :- copy(L1,L2).

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(_,_) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM