Hi, Am 24.01.2017 00:14, schrieb Gavin Lambert:
On 24/01/2017 07:26, Olaf van der Spek wrote:
1. scope for formatting tags:
concat(format::hex<int>, 42, " is hex for ", concat(42)).str();
Here the inner concat will convert the 42 to its decimal representation, while the outer one converts the first 42 to its hex representation.
Wouldn't concat(hex(42), " is hex for", 42) make more sense?
+1. If you like persistent formatting states (and all the unexpected fun they cause when you forget to cancel them), use iostreams instead.
My proposal does not have anything similar to iostream manipulators. The conversion tags always extend to the whole concat parameter list, but not to enclosed calls to concat. There is no change in behavior that depends on the position of the conversion tag in the parameter list. Actually I think, we should be able to put all the conversion tags at the beginning of the parameter list.
3. results from concat() in a boost::range that is passed to join():
join(separator("\n"), my_files | transformed([](const std::filesystem::path& f) -> auto { return concat(f.filename, ": ", std::filesystem::file_size(f)); })).str();
Maybe I missed something, but what was the intended distinction between concat() and join()?
The distinction is the same as in many other languages: join() works on sequences, while concat() works on its parameters.
To me, as vocabulary words, concat() implies "concatenate without separator" and join() implies "concatenate with separator"; as such it seems unnecessary to explicitly decorate the separator here since it's a required parameter.
I see. The approach, we had here up to now was, to define formatting specifics as tag parameters at the beginning of the parameter list. If you give no separator to join() it just puts all the representations of the sequences objects in a row without any space in between. In Python the equivalent would be to join on the empty string: "".join(mySequence). Then, of course it is reasonable to use the same tags for join(), and concat(), and actually as well for format(), but there separator() is unused. I agree, that your definition is mostly consistent with what I found for other languages as well, but most of them also only use join() on sequences and concat() or equivalents on parameter lists. In languages, where join() is used on parameter lists as well, like Java or Perl, there is no other concatenation function. I guess, concat() usually has no separator in most languages, because you can easily put it in as additional parameters. With my proposal, it just comes for free.
(Both should accept either variadics or ranges, if that's not too complicated to arrange, though it's likely for join() to be used more often on ranges; concat() might be more evenly split, though probably leaning toward variadics.)
That part is not consistent with what I found from other languages. Just Perl and Java (from the list of languages I checked), use join() for both usecases, but they don't have anything else, that is like concat() then. All the other distinguish between concatenating a few parameters, and joining a sequence.
If "concat" is the outer layer anyway, I would return a std::string directly for convenience. It is easy to forget the trailing .str() and it does not look elegant.
Of course better proposals are welcome :-) Would you prefer the implicit conversion? If so, why?
Implicit is problematic with auto..
While that's true, I think the flexibility of returning a factory from concat() is more useful than the discomfort of either remembering the str() or using std::string explicitly as the type instead of auto (or using auto combined with explicit std::string construction).
I agree. Would you prefer str(), or implicit conversion? Christof