File.byLine should return dups?

Steven Schveighoffer schveiguy at yahoo.com
Fri Jun 4 12:43:18 PDT 2010


On Fri, 04 Jun 2010 15:35:06 -0400, Graham Fawcett <fawcett at uwindsor.ca>  
wrote:

> Hi folks,
>
> I expected this program to print the lines of a file in reverse order:
>
>     // bad.d
>     import std.stdio;
>     import std.range;
>    void main() {
>       auto f = File("bad.d");
>       foreach(char[] line; retro(array(f.byLine())))
>         writeln(line);
>     }
>
> ...but instead it prints a jumble of line fragments. I suspect that
> it's because byLine() is not dup'ing the arrays it's reading from the
> file?
>
> This version works:
>
>     // good.d
>     import std.stdio;
>     import std.range;
>    Retro!(char[][]) retroLines(File f) {
>      char[][] lines;
>       foreach(line; f.byLine())
>         lines ~= line.dup;		// note the .dup!
>       return retro(lines);
>     }
>    void main() {
>       auto f = File("good.d");
>       foreach(line; retroLines(f))
>         writeln(line);
>     }
>
> ..but if you remove the '.dup' then it prints a similar mess.
>
> So, is there a bug in byLine(), or am I just using it wrong?

The latter.  File is re-using the buffer for each line, so you are seeing  
the data get overwritten.  This is for performance reasons.  Not everyone  
wants incur heap allocations for every line of a file   As you showed,  
it's possible to get the desired behavior if you need it.  The reverse  
would be impossible.

Now, that being said, a nice addition would be to create a duper range  
that allows you to do one expression:

foreach(char[] line; retro(array(duper(f.byLine()))))

-Steve

Copied from my .announce reply :)


More information about the Digitalmars-d mailing list