Input ranges do not compose

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Wed Dec 2 16:44:47 PST 2009


Sergey Gromov wrote:
> Say I want to present a file as an input range:
> 
> class RangeFile {
>     bool empty() {...}
>     ubyte front() {...}
>     void popFront() {...}
>     // some private stuff
> }
> 
> I'm parsing it.  There are chunks, one byte for size then data of that 
> size:
> 
> void parse(RangeFile rf) {
>     while (!rf.empty) {
>         int size = rf.front;
>         rf.popFront();
>         popFrontN(rf, size);
>     }
> }
> 
> It works.  Now let's do something useful with the chunks' contents. 
> There are strings in there, byte for length, then that much characters. 
>  Read 'em:
> 
> void parse(RangeFile rf) {
>     while (!rf.empty) {
>         int size = rf.front;
>         rf.popFront();
>         auto chunk = take(size, rf);
>         while (!chunk.empty) {
>             int len = chunk.front;
>             chunk.popFront();
>             auto str = new char[len];
>             copy(take(len, chunk), str);
>         }
>     }
> }
> 
> BANG.  This does not work.  The chunk won't end where it should.  The 
> problem is that second take() creates a copy of the chunk data, and the 
> copy() does not update chunk's remaining size while copying.
> 
> This behavior is fine and expected and desired for forward ranges and up 
> but makes no sense for input ranges.
> 
> I thought I could fix it rewriting copy:
> 
> copy(take(len, &chunk), str);
> 
> But it didn't compile.  Told me something about something not being lvalue.
> 
> There are actually two issues:
> 
> 1.  Most of the std.algorithm and std.range functions claim that they 
> accept input ranges but take them *by value*.  This violates input 
> ranges' non-copyable contract.
> 
> 2.  A whole bunch of algorithms is required similar to those we have now 
> but accepting their range arguments by reference and mutating them.
> 
> Do I miss something?  The ranges do not seem as universal to me anymore.

This issue is solved by save(), see 
http://erdani.com/publications/on-iteration.html. We need to make one 
more pass through the ranges and the range-related stuff in Phobos to 
use save().

Andrei



More information about the Digitalmars-d mailing list