digitalmars.D - immutable range
- kenji hara <k.hara.pg gmail.com> Oct 16 2011
- "Steven Schveighoffer" <schveiguy yahoo.com> Oct 17 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
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 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
Oct 17 2011








"Steven Schveighoffer" <schveiguy yahoo.com>