std.algorithm.joiner unexpected behavior
Sergei Degtiarev via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Mon Sep 11 07:37:14 PDT 2017
On Friday, 1 September 2017 at 00:09:16 UTC, H. S. Teoh wrote:
> Consider the case where .front returns a subrange. As you
> state above, copying this subrange does not have defined
> behaviour. One reason is the difference in semantics between
> reference types and value types: the assignment operator `=`
> means different things for each kind of type. `x=y;` for a
> value type makes a new copy of the value in x, but `x=y;` for a
> reference type only copies the reference, not the value.
Absolutely, in particular, InputRange shouldn't be assumed
copyable.
joiner saves whatever was passed to it, in this particular case,
result of
files.map!(a => a.byLine) which is range itself and is evaluated
lazily. This makes every call of .front() to re-evaluate (a =>
a.byLine) and to call the constructor again, skipping first line
every time.
The partial solution is simple, force joiner to make immediate
evaluation instead of lazy one:
return joiner(array(files.map!(a => a.byLine)));
here, the array is saved in joiner and no lazy constructor call
is performed. However, in general I have a feeling that something
is wrong here with design. Copying of InputRanges should be
disabled possibly, or lazy range evaluation should be under
control. Can't say what is wrong exactly, but something
definitely is.
More information about the Digitalmars-d-learn
mailing list