Ranges and/versus iterators

Steven Schveighoffer schveiguy at yahoo.com
Tue Mar 23 13:46:57 PDT 2010


On Tue, 23 Mar 2010 16:34:24 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail at erdani.org> wrote:

> On 03/23/2010 02:45 PM, Fawzi Mohamed wrote:
>> Andrei, as the topic just came up a comment on the range interface.
>> Just for plain forward iterators iterators having
>>
>> bool empty()
>> E front()
>> void popFront()
>>
>> makes the interface non reentrant.
>> For that purpose having a single function is better.
>> I use
>>
>> bool popFront(ref T t)
>> // returns true if there is a next element, and in that case returns it
>> in t
>>
>> this can be used by several consumers concurrently without problems and
>> creating filters, combiners,... is simple.
>> Another advantage is that a single object can implement several  
>> iterators.
>> A disadvantage is that even if there is a single iterator D makes type
>> inference cumbersome, i.e. you cannot simply use auto, as in a loop you
>> have to declare the variable before using it as the loop is
>> T a;
>> while (it.popFront(a)){
>> //...
>> }
>
> We've discussed this extensively, and I lost sleep over this simple  
> matter more than once. The main problem with bool popFront(ref E) is  
> that it doesn't work meaningfully for containers that expose references  
> to their elements.
>
> The interface with front() leaves it to the range to return E or ref E.
>
> An alternative is this:
>
> bool empty();
> ref E getNext(); // ref or no ref
>
> I'm thinking seriously of defining input ranges that way. The underlying  
> notion is that you always move forward - getting an element is  
> simultaneous with moving to the next.

A while back, you identified one of the best interfaces for input ranges:

E* getNext();

Which allows for null returns when no data is left.  The drawback is that  
E must be either referenced or allocated on the heap (providing storage to  
the function is an option).  But the killer issue was that safeD would not  
allow it.  However, in recent times, you have hinted that safeD may allow  
pointers, but disallow bad pointer operations.  In light of this, can we  
reconsider this interface, or other alternatives using pointers?

I've always felt that if we were to define ranges for streams in a  
non-awkward way, we would need an "all in one" operation, since not only  
does getting data from the range move the range, but checking for empty  
might also move the range (empty on a stream means you tried to read and  
got nothing).

-Steve



More information about the Digitalmars-d mailing list