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