Array of byLineCopy ranges behaves as they are byLine

ag0aep6g anonymous at example.com
Mon Mar 11 17:04:56 UTC 2019


On Monday, 11 March 2019 at 15:23:53 UTC, HaraldZealot wrote:
> ```d
> File[] files;
> foreach(filename; args[1 .. $])
> {
>     files ~= File(filename, "r");
> }
>
> auto ranges = files.map!(a => a.byLineCopy);
>
> writeln(ranges[0].front);
> writeln(ranges[0].front);
> writeln(ranges[0].front);
> ```
> produces
> ```
> 1
> 2
> 3
> ```
[...]
> What I'm doing wrong with `map`? Or is this a bug?

`map` is lazy in the sense that it (re-)evaluates the given 
function whenever you access an element. That means you're 
calling `byLineCopy` three times on the same file. Your code 
effectively does this:

     writeln(files[0].byLineCopy.front);
     writeln(files[0].byLineCopy.front);
     writeln(files[0].byLineCopy.front);

The range created by `byLineCopy` immediately reads a line from 
the file to populate its `front`. So you're reading three lines 
from the file.

Strictly speaking, I don't think any of this qualifies as a bug. 
`map`'s behavior might be surprising, but it's deliberate, as far 
as I know.

To avoid the re-evaluation, assign `ranges[0]` to a variable 
before using it:

     auto lines = ranges[0];
     writeln(lines.front);
     writeln(lines.front);
     writeln(lines.front);

That should print the same line three times.


More information about the Digitalmars-d-learn mailing list