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