getNext

Rory McGuire rmcguire at neonova.co.za
Mon Jul 12 23:48:48 PDT 2010


On Tue, 13 Jul 2010 06:38:55 +0200, Andrei Alexandrescu  
<SeeWebsiteForEmail at erdani.org> wrote:

> On 07/12/2010 11:21 PM, Jonathan M Davis wrote:
>> On Monday 12 July 2010 20:48:05 Andrei Alexandrescu wrote:
>>> I think I figured out a comfortable and all-encompassing means to  
>>> define
>>> a simplified interface for an input range.
>>>
>>> Currently input ranges need to define empty, front, and popFront. That
>>> works but it's a bit heavy for simple input ranges. We've been
>>> discussing simplified interfaces in this group but couldn't find one
>>> that satisfied all use cases.
>>>
>>> Consider this:
>>>
>>> T* getNext(R, T)(ref R range, ref T item);
>>>
>>> Semantics: if the range wants to expose addresses of its elements, it
>>> returns a pointer to the current element and also advances to the next
>>> element. Otherwise (i.e. the range does not have or does not want to
>>> expose addresses of its elements), the range fills "item" with the
>>> current value, again moves on to the next value, and returns&item.
>>>
>>> In all cases, when there are no more elements in the range, getNext
>>> returns null.
>>>
>>> getNext is easy to define for e.g. arrays and files. How does it sound?
>>> Does it bring significant simplification?
>>>
>>>
>>> Andrei
>>
>> What happens to empty, front, and popFront then? Is this a case where  
>> something
>> must define either empty, front, and popFront or getNext to be an input  
>> range? Or
>> is this something else? Personally, I find empty, front, and popFront  
>> quite
>> useful and simple for anything that I've done, and I'd find getNext to  
>> be a lot
>> more verbose. getNext may be great if you're using empty, front, and  
>> popFront
>> pretty much simultaneously, but if you don't want to use all of them for
>> whatever you're doing, then getNext is overkill.
>
> An input range could either define the troika empty/front/popFront or  
> getNext. In the former case, getNext detects the presence of the troika  
> and uses it transparently. That's great because client code can simply  
> use getNext throughout.
>
>> So, essentially, I suppose the issue is that I don't see what you  
>> intend to do
>> to front, popFront, and empty if you add getNext into the mix.
>
> There is no aggravation brought to the current definitions.
>
>> I do not want to
>> see front, popFront, or empty go away. Having getNext as an additional  
>> function
>> to make it easier to iterate over a range and do something with each  
>> element as
>> you iterate wouldn't hurt my feelings any, but I definitely don't want  
>> to lose
>> popFront, empty, or front.
>
> My feelings too. The troika is here to stay, and definitely necessary  
> for any range richer than an input range.
>
>> As for simplification, it strikes me as more complicated in every case  
>> except
>> where you are iterating over a range and processing each element as you  
>> iterate.
>> Granted, that's a common use case, but there are plenty of other cases,  
>> where if
>> you were forced to use getNext instead of having popFront, empty, and  
>> front,
>> that would be a major problem.
>
> Yah, truth be told getNext won't win a prize for brevity. You need to  
> define both a variable and a pointer to use it:
>
> T meh;
> T * neh;
> while ((neh = getNext(r, meh))) {
>     ... process *neh ...
> }
>
> I've just had an idea that is so dark and devious, I was almost afraid  
> to try it. But it works like a charm. Consider:
>
> T * getNext(R, E)(ref R range,
>                    ref E store = *(cast(E*) alloca(E.sizeof))
> {
>      ...
> }
>
> With this, allocating a dummy buffer on caller's stack is automated, so  
> client code can just write:
>
> for (T * p; (p = getNext(r)); )  {
>     ... process *p ...
> }
>
> I feel dirty.
>
>
> Andrei

:) I like it.

But then looking at the alloca man page... yikes


More information about the Digitalmars-d mailing list