Boost logo

Boost :

Subject: Re: [boost] Variadic append for std::string
From: Christof Donat (cd_at_[hidden])
Date: 2017-01-19 10:27:04


Am 19.01.2017 15:12, schrieb Hans Dembinski:
> Hi Christof and Richard,
>
>> On 18 Jan 2017, at 16:11, Christof Donat <cd_at_[hidden]> wrote:
>> I do like the idea, but not the naming. With a function name "join"
>> I'd expect to be able to pass an iterator range and have all its
>> element concatenated into a string with a defined separator like this:
>
> please don't change the name. I don't see why "join" implies
> iterators. "join" is a standard name for similar functions which join
> strings in other languages, e.g.
>
> Python

https://docs.python.org/3/library/stdtypes.html#str.join

", ".join(my_numbers)

versus

"Hello" + ", " + "World"

or - a bit arkward

", ".join(["Hello", "World"])

or

"Hello".append(", ").append("World")

> Perl

join($sep, @array)

versus

jon($sep, a, b, c, d)

> C#

https://msdn.microsoft.com/de-de/library/57a79xd0(v=vs.110).aspx

String.join(sep, string_arr);

versus

String.concat(a, b);

> Java

https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#join-java.lang.CharSequence-java.lang.Iterable-

String.join(sep, some_iterable);

versus

String.join(sep, a, b, c, d);

> JavaScript

https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Array/join

my_array.join(sep)

versus

String.concat(a, b, c, d);

While all languages, you named, support the idea of join(), to work on
iterables, only Java, and Perl reuse the name for parameter lists, as
well. Python can be shoehorned to concatenate with join(). Where I
proposed to use the word concat(), Python uses the operator +, or
append(), while C# and JavaScript call that concat().

Actually consistency with the experience from other languages is exactly
my concern here. We already have operator + and operator += for string
concatenation, but they are not the most efficient solutions.

> There is also the Qt library which has a QStringList::join method.

https://doc.qt.io/qt-5/qstringlist.html#join

Yes. Again just like I proposed to use that word. Thanks for making my
point. For concatenation of QStrings you'd use append(), push_back or
operator +:

s.append("Hello").append(", ").append("World");
s.push_back("Hello").push_back(", ").push_back("World");
s += "Hello" + ", " + "World");

> "join" is well established and a short word, too, certainly better
> than "concat", which has to be abbreviated to not be too long.

Yes, join is well established for a specific use case. I just ask not to
use it for a different one. Instead my proposal includes a join()
function, that works just like you'd expect from the established word.

> I have more arguments. The word "concatenate" sounds awkward and
> artificial. "join" is a word you use in daily conversations,
> "concatenate" is not. Google search for "join" yields 3e9 hits, Google
> search for "concatenate" yields 3e6 hits, so you can say "join" is
> about 1000x more common. I personally hate technical jargon in any
> field. Language was invented to include, not to exclude.

There are two distinct concepts, we'll have to either use to distinct
words or resort to overloading the same as Java and Perl do. Since I
like to call different things differently I'd propose to go the way, C#
and JavaScript go.

> Finally, "concatenate" in other programming contexts usually means
> that you append one collection to another collection.

See above.

To make things clear, a naive implementation of join, that only supports
strings could look like this:

template<typename Iterator>
auto join(const std::string& separator, Iterator i, Iterator end) ->
std::string {
     auro rval = std::ostringstream{};

     auto addSeparator = false;
     for(; i != end; ++i) {
         if( addSeparator ) rval << separator;
         else addSeparator = true;

         rval << *i;
     }

     return rval.str();
}

A naive implementation of concat(), could look like this:

auto concat_impl() -> std::ostringstream {
     return {};
}

template <typename LastArg, typename ... Args>
auto concat_impl(Args&& ... args, LastArg&& last_arg) ->
std::ostringstream {
     return concat_impl(std::forward(args)...) << last_arg;
}

template <typename ... Args>
auto concat(Args&& ... args) -> std::string {
     return concat_impl(std::forward(args)...).str();
}

Both implementations are untested. They are just here to emphasize my
point.

Christof


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk