Thread overview
[Issue 5351] Add template mixin for Range Primitives using random access
Dec 09, 2015
Infiltrator
Feb 11, 2016
Jesse Phillips
Oct 30, 2017
Eduard Staniloiu
Oct 30, 2017
Simen Kjaeraas
Dec 01, 2017
Jesse Phillips
Dec 04, 2017
Simen Kjaeraas
Mar 05, 2023
Paul Backus
December 09, 2015
https://issues.dlang.org/show_bug.cgi?id=5351

Infiltrator <lt.infiltrator@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |lt.infiltrator@gmail.com

--- Comment #1 from Infiltrator <lt.infiltrator@gmail.com> ---
Are you suggesting that this boilerplate mixin should be added to phobos?  It seems too inflexible for general use.

--
February 11, 2016
https://issues.dlang.org/show_bug.cgi?id=5351

--- Comment #2 from Jesse Phillips <Jesse.K.Phillips+D@gmail.com> ---
(In reply to Infiltrator from comment #1)
> Are you suggesting that this boilerplate mixin should be added to phobos? It seems too inflexible for general use.

Yes that is what's being requested http://forum.dlang.org/post/rewptfpubrsjifwblump@forum.dlang.org

I agree it isn't flexible, that isn't the point. It only has to do one thing well.

--
October 30, 2017
https://issues.dlang.org/show_bug.cgi?id=5351

Eduard Staniloiu <edi33416@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |bootcamp
                 CC|                            |edi33416@gmail.com

--
October 30, 2017
https://issues.dlang.org/show_bug.cgi?id=5351

Simen Kjaeraas <simen.kjaras@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |simen.kjaras@gmail.com

--- Comment #3 from Simen Kjaeraas <simen.kjaras@gmail.com> ---
The implementation above will fail for this simple case:

MyRange!int a = [1,2,3];
a.popFront();
assert(a[0] == a.front);

It could be made to work for ranges that support slicing, and assignment from the slice to the range:

void popFront() {
    this = this[1..$];
}

front and empty are then trivial calls to this[0] and length == 0, respectively.

One option that only requires opIndex and length would use a wrapper struct. This solution would leave MyRange as a non-range, though - only its sliced result would be a range:

struct MyRange(T) {
    T[] arr;
    T opIndex(size_t idx) {
        return arr[idx];
    }

    @property
    size_t length() {
        return arr.length;
    }

    mixin rangeFuncs!();
}

template rangeFuncs() {
    auto opSlice() {
        alias TT = typeof(this);
        struct Result {
            size_t _index;
            TT* _range;

            auto front() {
                return (*_range)[_index];
            }

            @property
            bool empty() {
                return _index == _range.length;
            }

            void popFront() {
                _index++;
            }

            auto opIndex(size_t idx) {
                return (*_range)[_index + idx];
            }
        }

        Result result;
        result._range = &this;
        return result;
    }
}

unittest {
    import std.range.primitives : isInputRange;
    import std.algorithm.comparison : equal;

    auto a = MyRange!int([1,2,3,4]);

    static assert(!isInputRange!(typeof(a)));
    static assert(isInputRange!(typeof(a[])));
    assert(a[].equal([1,2,3,4]));
}

In conclusion, opIndex + length is insufficient functionality to turn something into a range.

--
December 01, 2017
https://issues.dlang.org/show_bug.cgi?id=5351

--- Comment #4 from Jesse Phillips <Jesse.K.Phillips+D@gmail.com> ---
(In reply to Simen Kjaeraas from comment #3)
> The implementation above will fail for this simple case:
> 
> MyRange!int a = [1,2,3];
> a.popFront();
> assert(a[0] == a.front);
> 
> It could be made to work for ranges that support slicing, and assignment from the slice to the range:
> 
> void popFront() {
>     this = this[1..$];
> }

Actually this would be a good verification to add to isRandomAccessRange because your correct that this wouldn't match for random access, but such a behavior is fine for forward and bidirectional.

Now that being said, the confusion of having an indexable, non-randomAccessRange with this kind of behavior would be there.

--
December 04, 2017
https://issues.dlang.org/show_bug.cgi?id=5351

Simen Kjaeraas <simen.kjaras@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|---                         |INVALID

--- Comment #5 from Simen Kjaeraas <simen.kjaras@gmail.com> ---
isRandomAccessRange is a compile-time construct, and checking foo[0] == foo.front is generally not possible at compile-time. Even if it is, the fact they're equal right now doesn't mean they always will be (consider the fibonacci sequence 1,1,2,3,5,8,13,21..., which would have foo[0] == foo.front after one popFront, but not two).

In addition, as you say, having an indexable range with semantics different from random access ranges is not at all desirable, and a recipe for disaster at some later point.

I agree having this kind of functionality in Phobos would be nice, but I don't see a workable path to that goal. I'm closing this - please reopen if there are revelations that make it possible in the future.

--
March 05, 2023
https://issues.dlang.org/show_bug.cgi?id=5351

Paul Backus <snarwin+bugzilla@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
                 CC|                            |snarwin+bugzilla@gmail.com
         Resolution|INVALID                     |---

--- Comment #6 from Paul Backus <snarwin+bugzilla@gmail.com> ---
Reopening this, since the proposed addition is still useful, even if (as discussed) it would require more from the "host" type than just indexing and length.

--