ideas about ranges

Steven Schveighoffer schveiguy at yahoo.com
Fri May 22 13:32:25 PDT 2009


On Fri, 22 May 2009 15:55:52 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail at erdani.org> wrote:

> Steven Schveighoffer wrote:
>> Another idea is to make the T the ref'd arg, similar to how the system  
>> call read() works:
>>  bool popNext(ref T);
>>  This has some benefits:
>>  1) you aren't checking a temporary for emptyness, so it fits well  
>> within a loop construct
>> 2) you can avoid returning a dummy element in the empty range case.
>> 3) you avoid returning a piece of possibly large data on the stack when  
>> it's probably just going to get copied anyways (although the compiler  
>> can sometimes optimize this).
>
> We considered that as well. It is problematic because looking at  
> elements always entails copying them, which is rather silly if you do it  
> for e.g. an array.

This is why I was suggesting that foreach has to support both the simple  
popNext API and the range API.  Which sucks, but I can't see a way around  
it without using pointers...

>
> By golly, I kid you not but the interface I personally like the most is:
>
> struct ArchetypalInputRange(T)
> {
>      T* popNext();
> }
>
> popNext returns a pointer to a T (the value may be reused) or null when  
> the range is done. Iteration becomes easy and efficient for all types.  
> An input range would still have to keep a buffer (and return a pointer  
> to it), but things are not awkward to implement.
>
> Given the bad reputation that pointers have, I guess people wouldn't  
> like this all that much.

Then maybe we have to come up with a better pointer...  I kind of like the  
way classes work for this.  Comparing them to null does what you want it  
to do, but doing anything else with it forwards to the underlying data.   
It's rebindable, and you can't do arithmetic on the pointer.

ref accomplishes all of this, except you can't get at the underlying  
pointer to do things like compare to null or rebind.  Maybe we simply need  
some new operators to get at the ref addresses.

ref T popNext();
ref T t; // initialized to null
while((t =& popNext()) ==& null)
...
Still doesn't look as good as:

while(auto t = popNext())

Hm.. what about returning an array of 0 or one element? (ugh).

What about a type which acts like a class reference for simple data types:

struct rref(T)
{
   prviate T *data;
   ref T opStar() {return *data;}
   ref T opDot() {return *data;}
   void opAssign(ref T t) {data = &t;}
}

Need some compiler help to allow comparing to null, probably want this to  
be a builtin type, and have some better syntax.

BTW, I like your solution the best too.  I thought of using pointers, but  
decided against it because of the taboo factor.

-Steve



More information about the Digitalmars-d mailing list