I need to duplicate list in prolog.
I have list:
L = [a(string1,value1),a(string2,value2),a(string3,value3),a(string4,value4)].
Out
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).
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(_,_)
.
pattern matching is used to decompose arguments: you can do
copy([],[]).
copy([a(H,_)|L1],[H|L2]) :- copy(L1,L2).