immutable range

Steven Schveighoffer schveiguy at yahoo.com
Mon Oct 17 05:29:18 PDT 2011


On Sun, 16 Oct 2011 07:37:03 -0400, kenji hara <k.hara.pg at gmail.com> wrote:

> I got an idea.
>
> import std.range;
>
> template isImmutableInputRange(R)
> {
>     enum bool isImmutableInputRange = is(typeof(
>     {
>         R r;                    // can define a range object
>         if (r.empty) {}         // can test for empty
>         auto r2 = r.nextFront(); // can invoke nextFront()
>         auto h = r2.front;      // can get the front of the range
>     }));
> }
>
> template isImmutableForwardRange(R)
> {
>     enum bool isImmutableForwardRange = isImmutableInputRange!R &&  
> is(typeof(
>     {
>         R r1;
>         R r2 = r1.save; // can call "save" against a range object
>     }));
> }
>
> template isImmutableBidirectionalRange(R)
> {
>     enum bool isImmutableBidirectionalRange = isImmutableForwardRange!R
>         && is(typeof(R.init.back()) == typeof(R.init.front()))
>         && is(typeof({ R r; auto r2 = r.nextBack(); }));
> }
>
> void immutableForeach(R, E)(R r, scope void delegate(E) dg)
> if (isImmutableInputRange!R && is(ElementType!R : E))
> {
>     if (r.empty)
>         return;
>     dg(r.front);
>     immutableForeach(r.nextFront(), dg);        // tail recursion
> }
> void immutableForeachReverse(R, E)(R r, scope void delegate(E) dg)
> if (isImmutableBidirectionalRange!R && is(ElementType!R : E))
> {
>     if (r.empty)
>         return;
>     dg(r.back);
>     immutableForeachReverse(r.nextBack(), dg);  // tail recursion
> }
>
> const struct Range
> {
>     int[] arr;
>
>     @property int front() const { return arr[0]; }
>     @property bool empty() const { return arr.length > 0; }
>     const(Range) nextFront() const { return Range(arr[1..$]); }
>
>     const(Range) save() const { return this; }
>
>     @property int back() const { return arr[$-1]; }
>     const(Range) nextBack() { return Range(arr[0..$-1]); }
> }
>
> static assert(isImmutableInputRange!Range);
> static assert(isImmutableForwardRange!Range);
> static assert(isImmutableBidirectionalRange!Range);
>
> void main()
> {
>     const r = Range([1,2,3]);
>
>     int i = 0;
>     immutableForeach(r, (int v)
>     {
>         assert(v == ++i);
>     });
>
>     int j = 3;
>     immutableForeachReverse(r, (int v)
>     {
>         assert(v == j--);
>     });
> }
>
> Kenji Hara

I don't think this scales well.  Not only are you introducing a new type  
of range, you are introducing a new *class* of range.  One which does not  
work with any existing algorithms.

The solution must be compatible with all the existing range functions  
(which do not modify data), or it doesn't work.

-Steve


More information about the Digitalmars-d mailing list