Forward ranges in Phobos v2

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Thu Nov 4 04:06:15 UTC 2021


On 11/3/21 11:25 PM, Paul Backus wrote:
> On Wednesday, 3 November 2021 at 17:41:10 UTC, Andrei Alexandrescu wrote:
>> On 2021-11-03 12:18, Paul Backus wrote:
>>> On Wednesday, 3 November 2021 at 15:40:41 UTC, Andrei Alexandrescu 
>>> wrote:
>>>> On 2021-11-02 20:38, Paul Backus wrote:
>>>>>
>>>>> auto next(R)(ref R r)
>>>>>      if (isForwardRangeV2!R && isMutable!R)
>>>>> {
>>>>>      alias E = ElementType!R;
>>>>>      if (r.empty)
>>>>>          return none!E();
>>>>>      else
>>>>>      {
>>>>>          auto result = some(r.head);
>>>>>          r = r.tail;
>>>>>          return result;
>>>>>      }
>>>>> }
>>>>
>>>> OK, so the signature of next for all ranges is:
>>>>
>>>> Option!(ElementType!R) next(Range)(ref Range);
>>>>
>>>> Is that correct?
>>>
>>> More precisely, to use the Phobos convention: `is(ReturnType!((Range 
>>> r) => r.next) == Option!(ElementType!R))`.
>>>
>>> So, `next` could be a function, a @property, or a member variable, 
>>> and it does not necessarily require an lvalue to call (just like 
>>> `front` today).
>>
>> We've considered this way back when. I'm talking like 2006. It was 
>> like this:
>>
>> T next(Range)(ref Range r, ref bool done);
>>
>> The main problem is that iterating such a forward range would entail a 
>> copy of each element of the range. This is not scalable in general.
>>
>> This is a showstopper.
> 
> If we want to avoid copying, we can have `next` return a `Ref!T` in the 
> case where the forward range has lvalue elements:
> 
> struct Ref(T)
> {
>      T* ptr;
> 
>      ref inout(T) deref() inout
>      {
>          return *ptr;
>      }
>      alias deref this;
> }
> 
> I've tested some simple uses of this wrapper on run.dlang.io, and it 
> seems like DIP 1000 is good enough to make it work in @safe code.
> 
> If "returns either `T` or `Ref!T`" sounds like a suspect design for an 
> API, consider that it is basically the same thing as an `auto ref` 
> return value--just with the distinction between ref and non-ref brought 
> inside the type system.

That was on the table, too, in the form of a raw pointer.

I think it can be made to work, but for lvalue ranges only, and it will 
be difficult to make safe (scoped etc).

Overall this seems to create more problems than it solves.


More information about the Digitalmars-d mailing list