File.byLine should return dups?

Graham Fawcett fawcett at uwindsor.ca
Fri Jun 4 13:07:35 PDT 2010


On Fri, 04 Jun 2010 19:58:43 +0000, Graham Fawcett wrote:

> Hi Steven,
> 
> On Fri, 04 Jun 2010 15:43:18 -0400, Steven Schveighoffer wrote:
> 
>> 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.
>> 
>> 
> Thanks for the response. Yes, it makes mode to favour performance for
> the common case, and as you say it's not hard to resolve this issue.
> 
>> 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()))))
> 
> Yes -- duper (and iduper) for the win! Great idea.

It just occurred to me that duper/iduper could be defined as

alias map!("a.dup") duper;
alias map!("a.idup") iduper;

Thanks for suggesting duper, I like that idea very much. :)

Graham


> 
>> -Steve
>> 
>> Copied from my .announce reply :)
> 
> Sorry again for the .announce posting. :P
> 
> Graham



More information about the Digitalmars-d mailing list