Skip to main content
Code Review

Return to Question

Commonmark migration
Source Link

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

join

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

interleave

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.

#mapconcat

mapconcat

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.

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

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

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.

#mapconcat

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.

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

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

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.

mapconcat

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.

edited tags
Link
200_success
  • 145.6k
  • 22
  • 190
  • 479
Source Link
wvxvw
  • 1k
  • 7
  • 14

Repeated string concatenation

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

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

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.

#mapconcat

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.

default

AltStyle によって変換されたページ (->オリジナル) /