Comment #1 by bearophile_hugs — 2015-01-09T15:46:04Z
The short answer: do not use impure functions in higher order functions like map/filter, unless you know what you are doing (and you usually don't).
So it's better to find a pure way to solve your problem, like:
void main() {
import std.stdio, std.algorithm, std.array, std.range;
static a = ["a", "b", "c", "d", "e", "f", "g", "h", "i"];
zip(a, a).map!(p => p[0] ~ p[1]).joiner(", ").writeln;
}
Comment #2 by peter.alexander.au — 2015-01-11T12:23:01Z
This isn't a bug. You cannot make assumptions about how many times joiner will call .front. Since map is a forward range, you cannot assume that joiner will only iterate once. Like bearophile, I would highly recommend using pure functions with map.
Comment #3 by jack — 2017-02-07T18:55:49Z
Using side effects in range code is a recipe for disaster. From the std.range.isInputRange docs,
>The following are rules of input ranges are assumed to hold true in all Phobos code. These rules are not checkable at compile-time, so not conforming to these rules when writing ranges or range based code will result in undefined behavior.
>...
>r.front evaluated multiple times, without calling r.popFront, or otherwise mutating the range object or the underlying data, yields the same result for every evaluation.
This code breaks that assumption, as map does not cache the results of the lambda.
However this works,
import std.stdio, std.algorithm, std.array;
static a = ["a", "b", "c", "d", "e", "f", "g", "h", "i"];
void main()
{
size_t idx = 0;
writeln(a.map!(s => s ~ a[idx + 1 == a.length ? idx : ++idx]).cache.joiner(", "));
}
Closing as invalid.