digitalmars.D - immutable range
- kenji hara (70/70) Oct 16 2011 I got an idea.
- Steven Schveighoffer (7/78) Oct 17 2011 I don't think this scales well. Not only are you introducing a new type...
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
Oct 16 2011
On Sun, 16 Oct 2011 07:37:03 -0400, kenji hara <k.hara.pg 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 HaraI 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
Oct 17 2011