immutable range

kenji hara k.hara.pg at gmail.com
Sun Oct 16 04:37:03 PDT 2011


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


More information about the Digitalmars-d mailing list