digitalmars.D.bugs - [Issue 15972] New: joiner doesn't recognize range of chars
- via Digitalmars-d-bugs (65/65) Apr 29 2016 https://issues.dlang.org/show_bug.cgi?id=15972
https://issues.dlang.org/show_bug.cgi?id=15972 Issue ID: 15972 Summary: joiner doesn't recognize range of chars Product: D Version: D2 Hardware: All OS: All Status: NEW Severity: normal Priority: P1 Component: phobos Assignee: nobody puremagic.com Reporter: hsteoh quickfur.ath.cx 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. --
Apr 29 2016