Code:
-------
auto triangle(int i) {
import std.algorithm.iteration : map, joiner;
import std.range : iota, repeat;
return iota(i).map!(i => '#'.repeat(i))
.joiner("\n");
}
void main() {
import std.stdio : writeln;
writeln(triangle(10));
}
-------
Compile error:
-------
test.d(5): Error: template std.algorithm.iteration.joiner cannot deduce function from argument types !()(MapResult!(__lambda2, Result), string), candidates are:
/usr/src/d/phobos/std/algorithm/iteration.d(1949): std.algorithm.iteration.joiner(RoR, Separator)(RoR r, Separator sep) if (isInputRange!RoR && isInputRange!(ElementType!RoR) && isForwardRange!Separator && is(ElementType!Separator : ElementType!(ElementType!RoR)))
/usr/src/d/phobos/std/algorithm/iteration.d(2232): std.algorithm.iteration.joiner(RoR)(RoR r) if (isInputRange!RoR && isInputRange!(ElementType!RoR))
-------
A little sleuthing with pragma(msg) reveals that the problem is caused by '#'.repeat(i) returning a range of char (as opposed to a range of dchar, which is what usually happens when strings are used with joiner), but strings (as well as char literals such as writing '\n' instead of "\n") are always ranges of dchar (no thanks to autodecoding), so joiner's signature constraints will fail because it tries to check implicit conversion of the delimiter element type (in this case always dchar) to the target range type (char), and is(dchar : char) is false.
Workaround:
--------
auto triangle(int i) {
import std.algorithm.iteration : map, joiner;
import std.range : iota, repeat;
import std.utf : byCodeUnit; // this is a hack
return iota(i).map!(i => '#'.repeat(i))
.joiner("\n".byCodeUnit);
}
void main() {
import std.stdio : writeln;
writeln(triangle(10));
}
--------
This is very silly, since nobody not already familiar with the intricacies of autodecoding will even have the slightest idea what the problem is and how to work around it. My personal recommendation: kill autodecoding with fire.
Comment #1 by dfj1esp02 — 2016-05-05T14:16:41Z
What I have in mind:
1. Move autodecoding algorithms to undead.
2. Remove autodecoding from algorithms.
3. Have dfix rewrite std.algorithm to undead.algorithm
Comment #2 by greensunny12 — 2018-03-31T19:11:56Z
> What I have in mind:
> 1. Move autodecoding algorithms to undead.
> 2. Remove autodecoding from algorithms.
> 3. Have dfix rewrite std.algorithm to undead.algorithm
How would that work in practice?
std.algorithm is highly templated and the big issue are the auto-decoding primitives in std.range.
We can't remove them easily nor even version them out (see e.g. https://github.com/dlang/phobos/pull/5513) and no one seems to have found a good transition path so far.
For now .byCodeUnit is the only available workaround and maybe eventually RCString gets a thing.
Comment #3 by dfj1esp02 — 2018-08-03T11:43:41Z
(In reply to Seb from comment #2)
> and no one seems to have found a good transition path so far.
I mean replace std.algorithm with undead.algorithm in sources.
Comment #4 by robert.schadek — 2024-12-01T16:26:40Z