I've been looking for a way to have a predicate that establishes that all elements of a list are substrings delimited by a given string. Analogues in other languages include: 'delimiter'.join(list) in Python, (mapconcat function sequence delimiter) in Emacs Lisp, array.join('delimiter') in JavaScript, and I'm sure there are more of the kind. Below are three different variants I came up with, but I've a strong feeling that I'm reinventing the wheel here:


join(_, [X], X) :- !.
join(Sep, [X | Xs], S) :-
    join(Sep, Xs, Sx),
    string_concat(Sep, Sx, Sy),
    string_concat(X, Sy, S).

Seems to be the simplest, but I don't like that it is not tail-recursive and that it has an obvious repetitive pattern.


interleave([X], _, X) :- !.
interleave([X | Xs], Glue, Result) :-
    interleave(Xs, Glue, Previous),
    format(atom(Result), "~p~p~p", [X, Glue, Previous]).

Still not tail-recursive, no repetition, but I'm not sure how bad is format if compared to plain string_concat.


reduce([], X, _, X) :- !.
reduce([X | Xs], Acc, Predicate, Result) :-
    call(Predicate, Acc, X, Interim), 
    reduce(Xs, Interim, Predicate, Result).
reduce([X | Xs], Predicate, Result) :- reduce(Xs, X, Predicate, Result).

mapconcat_helper(Glue, X, Y, Z) :- format(atom(Z), '~p~p~p', [X, Glue, Y]).

mapconcat(List, Glue, Result) :-
    reduce(List, mapconcat_helper(Glue), Result).

To my surprise, there isn't a reduce-like predicate in the standard library, so I had to write my own. Finally, this won't explode the stack for longer lists.

So, which one, if any of these is best? Perhaps there are libraries that already do this better? I'm using SWI Prolog, and am doing this mostly for self-education, so I'm not yet concerned with portability etc. If it's SWI-specific, I think it'd still do.

  • 2
    \$\begingroup\$ Check out foldl/4, for "reduce". The !/0 you added only makes your version less general than what you can do with foldl/4. \$\endgroup\$
    – mat
    Commented Apr 13, 2015 at 14:37
  • \$\begingroup\$ Thanks @mat, Was foldl added after 6.0.2? Because I'm sure I searched for fold, but didn't find it. I think I added ! due to instantiation mode of string_concat, but now I've checked and it works both ways, so... I don't know why I did it :) \$\endgroup\$
    – wvxvw
    Commented Apr 13, 2015 at 16:43
  • 1
    \$\begingroup\$ 6.0.2 is quite outdated, I recommend you upgrade to 7.1.36 or later. Soon, 7.2 will be released as a stable release within the 7.x development branch. foldl/4 is quite powerful and useful in many cases. Due to its completely relational nature, it can be used in more cases than may be apparent at first. \$\endgroup\$
    – mat
    Commented Apr 16, 2015 at 11:36

1 Answer 1


A quick browse through the SWI-Prolog manual finds atomics_to_string/3:

atomics_to_string(+List, +Separator, -String)

Creates a string just like atomics_to_string/2, but inserts Separator between each pair of inputs. For example:

?- atomics_to_string([gnu, "gnat", 1], ', ', A).
A = "gnu, gnat, 1"
  • \$\begingroup\$ It's funny, because I read that section of the manual, but didn't make a connection. Thanks for the effort! \$\endgroup\$
    – wvxvw
    Commented Apr 10, 2015 at 7:50
  • \$\begingroup\$ Also, worth noting. This predicate only exists in the development version 7.X.X and high, (stable versions 6.X.X don't have it). \$\endgroup\$
    – wvxvw
    Commented Apr 10, 2015 at 8:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.