Roger
Roger

Reputation: 31

Generating a new atom based on existing atom within a list

I would like to know how to generate a new atom in a list based on existing atom in another list. Given list:

L=[a,b,c,d]

I would like to produce a new list, for example:

P=[a_,b_,c_,d_]

In other words something similar to string addition, e.g.

String str1 = str2 + "_";

Upvotes: 3

Views: 172

Answers (2)

false
false

Reputation: 10102

The ISO built-in atom_concat/3 is the one to use here:

?- atom_concat(a,'_',A).
   A = a_.

But how to map now the entire list element-wise? maplist/3 serves this purpose,

?- maplist(atom_concat('_'), [a,b,c,d], Xs). % Wrong!
   Xs = ['_a','_b','_c','_d'].

... or almost. We added the underscore in front! maplist/3 like many other higher-order predicates adds the additional arguments at the end. In functional programming languages this is called partial application. But in our case, it would be nice to add one argument in front and one at the end. You could make your own definition, like

suffix_prefix_concat(S,P,C) :-
   atom_concat(P,S,C).

while this works nicely,

?- maplist(suffix_prefix_concat('_'),[a,b,c,d], Xs).
   Xs = [a_,b_,c_,d_].

... it has its own disadvantages: Inventing a new definition is often very cumbersome: Think of it, you have to figure out a new name for a single use! A general solution to this is library(lambda) which is preinstalled in YAP, you can download it for SWI too. See the link for a generic ISO definition which works in any ISO conforming system like GNU, B, SICStus.

?- maplist(\P^C^atom_concat(P,'_',C),[a,b,c,d],Xs).
   Xs = [a_,b_,c_,d_].

And since the last argument can be avoided, similarly to suffix_prefix_concat above, we can write more compactly:

?- maplist(\P^atom_concat(P,'_'),[a,b,c,d],Xs).
   Xs = [a_,b_,c_,d_].

Upvotes: 5

twinterer
twinterer

Reputation: 2436

Don't know if it's available in all Prolog systems, but concat_atom/2 would do the trick:

?- concat_atom([a,'_'], A).
A = a_.

Upvotes: 1

Related Questions