Overhauling the notion of output range

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Mon Jul 12 10:49:50 PDT 2010


On 07/12/2010 11:48 AM, Steven Schveighoffer wrote:
> On Mon, 12 Jul 2010 11:05:33 -0400, Andrei Alexandrescu
> <SeeWebsiteForEmail at erdani.org> wrote:
>
>> On 07/12/2010 09:59 AM, Steven Schveighoffer wrote:
>>> If I always have to do something like this in order to append a single
>>> element:
>>>
>>> put(r, (&elem)[0..1]);
>>
>> No, the library does that. Look here:
>>
>> http://www.dsource.org/projects/phobos/browser/trunk/phobos/std/range.d#L306
>>
>
> So you're saying it's not ok for an output range to support appending a
> single element, but it's ok for put to support appending a single element?

Yes. The point is that with a delegate you must choose between accepting 
E and E[]. Given the constraint, it's better for everyone to accept E[] 
and let put() take care of the occasional E by doing the wraparoo 
(&elem)[0..1].

> Well, all that will end up happening is cases where appending a single
> element is the only possibility will produce overloaded add functions,
> one that takes a single element, and one that takes an array. The one
> that takes an array will look like this:
>
> foreach(e; arr)
> add(e);

That's fine. the point is that if you put this loop on the wrong side of 
the delegate, it's much less efficient.

> I can tell you this for sure, because it's exactly what's in many
> dcollections classes.
>
> So what happens when you call put(r, e) for one of these output classes?
> Instead of just calling add(e), it calls (add((&e)[0..1])) which in turn
> goes through some needless loop, which then ends up calling add(e). I
> don't see why this is preferable.

Ah, I see. There is a confusion. The array restriction is only for 
delegates. For straight ranges, you should accept individual Es. Let me 
copy the current definition of isOutputRange:

template isOutputRange(R, E)
{
     enum bool isOutputRange = is(typeof(
     {
         R r;
         E e;
         r.put(e);          // can write element to range
     }()))
         ||
     isInputRange!R && is(typeof(
     {
         R r;
         E e;
         r.front = e;       // can assign to the front of range
     }()))
         ||
         is(typeof(
     {
         R r;
         E[] es;
         r(es);
     }()));
}

Notice how the E[] requirement is for delegates only.


Andrei


More information about the Digitalmars-d mailing list