File.byLine ought to return dups?
Steven Schveighoffer
schveiguy at yahoo.com
Fri Jun 4 12:41:43 PDT 2010
On Fri, 04 Jun 2010 15:27:03 -0400, Graham Fawcett <fawcett at uwindsor.ca>
wrote:
> Hi folks,
>
> I expected the following program to print the lines of a file in
> reverse:
>
> // bad.d
> import std.stdio;
> import std.range;
> void main() {
> auto f = File("bad.d");
> foreach(char[] line; retro(array(f.byLine())))
> writeln(line);
> }
>
> However, this produces very unusual output: fragments of the same
> lines are printed repeatedly. I suspect it's because the byLine()
> 'generator' is not dup'ing the arrays it reads from the file.
>
> This works as expected:
>
> // 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);
> }
>
> If you remove the '.dup', then this behaves badly as well.
>
> So is this a bug in File.byLine, or am I just using it badly? :)
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
More information about the Digitalmars-d-announce
mailing list