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