output ranges: by ref or by value?

Steven Schveighoffer schveiguy at yahoo.com
Sat Jan 2 15:16:25 PST 2010


On Sat, 02 Jan 2010 13:51:48 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail at erdani.org> wrote:

> Steven Schveighoffer wrote:
>>  Would it not be as useful then to just define attributes on the type  
>> and save a bunch of useless/weird looking code?
>>  that is, have an enum value inside the type that defines its state can  
>> be saved.  It seems to me like save is the equivalent of that anyways,  
>> since its possible to forget to use it, and still have your code  
>> compile.
>
> If you have an enum that says a range's state can be saved, then you  
> still need a function to effect that save :o). So you added, not  
> removed, bloat.

The function already exists -- opAssign.  My point is that save would just  
be the same as opAssign in most cases where you'd want to implement save.   
Cases where you'd want to implement save differently than opAssign are  
cases where you wouldn't want to use it in a generic fashion.

>
>> Basically, it appears to me that save either a) doesn't compile or b)  
>> is the equivalent of assignment.  It doesn't seem to add much to the  
>> functionality.
>
> No, for class ranges save() is nontrivial (a sort of clone). I suspect  
> even struct ranges for certain file-oriented stuff would do nontrivial  
> work (e.g. open the file anew and fseek() on the current position etc.)

Classes should not be ranges.  And I hope that any algorithm that uses  
savable ranges would not be used on a file range.  For example, your  
consume function:

bool consume(R1, R2)(ref R1 r1, R2 r2)
         if (isForwardRange!R1 && isInputRange!R2)
{
     auto r = r1.save();  // open an extra file, and seek the file to the  
given point *just in case*?!
     while (!r2.empty && !r.empty && r.front == r2.front) {
         r.popFront();
         r2.popFront();
     }
     if (r2.empty) {
         r1 = r;  // note that this unaliases r1 from any other copies (not  
save()'d copies) that were made of it.
                  // also note that you now have opened more handles to the  
same file.  Calling this many times could
                  // consume quite a few handles.
         return true;
     }
     return false;
}

Here is a good exercise that would help clarify what we need: determine  
all the types of ranges you can think of that would need a special save  
function.

>> This is all except for classes, which I think have no business being  
>> ranges in the first place.
>
> Well then how would the container hierarchy work? It does need range  
> interfaces. How does dcollections deal with that?

A container is not a range.  A range of a container should not be a  
class.  For dcollections, I was planning on ranges being a struct with a  
begin and end cursor defining the part of the container referenced by the  
range.  Such a range can always be copied and modifying the copy through  
the range functions should not modify the original range.

I see a range as being useful for iteration or algorithms, but not for  
general use.  A great example is AAs.  Would you say that an AA *is* a  
range or should *provide* a range?  If it is a range, does that mean you  
remove elements as you call popFront?  Does that make any sense?  If it  
doesn't, then what happens if you add elements through another alias to  
that AA?

-Steve



More information about the Digitalmars-d mailing list