import std.stdio : writefln,writef; struct Range { alias idouble inclusive; static Range opCall() { Range r; return r; } static Range opCall(size_t b) { Range r; with(r){begin = b; end = -1;} return r; } static Range opCall(size_t b, size_t e) { Range r; with(r){ begin = b; end = e;} return r; } static Range opCall(size_t b, inclusive e) { Range r; with(r){ begin = b; end = cast(size_t)e.im+1;} return r; } static Range opCall(size_t b, size_t e, int s) { Range r; with (r){begin = b; end = e; step = s;} return r; } static Range opCall(size_t b, inclusive e, int s) { Range r; with (r){ begin = b; step = s; end = (cast(size_t)e.im) + ((s > 0) ? 1 : -1); } return r; } static Range opCall(size_t b, void*n, int s) { Range r; with (r){begin = b; end = -1; step = s;} return r; } int opApply(int delegate(inout int) dg) { // use signed loop var to be safe if (step>0) { for (int i=begin; iiend; i+=step) { int ret = dg(i); if (ret) return ret; } } return 0; } int[] list() { if (step > 0 && end==-1) throw new Exception("Cannot convert an infinite to Range to array"); int[] ret; if (step>0) { for (int i=begin; iiend; i+=+step) { ret ~= i; } } return ret; } size_t begin=0; size_t end=-1; int step=1; } // Would be nice to be able to call this opIndex ;-) T[] slice(T,S)(T[] arr, S idx) { static if( is(S : Range) ) { alias idx r; size_t end = r.end; if (end == -1U && r.step>0) end = arr.length; if (r.step==1) { // Return a native slice return arr[r.begin..end]; } else { // Build a stepped slice T[] ret; if(r.step>0) { for(size_t i=r.begin; iiend; i+=r.step) { ret ~= arr[i]; } } return ret; } } else static if ( is(S v : v[])) { // Index by array T[] ret; static if ( is(typeof(idx[0]) : long) ) { foreach(i; idx) { ret ~= arr[i]; } } else { foreach(i; idx) { ret ~= arr.slice(i); } } return ret; } else { // Try regular index type // Would be nice if this could somehow return a plain // arr[idx], but I can't figure out how to make it so. return [arr[idx]]; } } class C { float[] opIndex(S)(S idx) { return m_arr.slice(idx); } float opIndex(S:int)(int i) { return m_arr[i]; } /* float[] opIndex(S)(int[] indexSet) { return m_arr.slice(indexSet); } float[] opIndex(Range range) { return m_arr.slice(range); } */ float m_arr[]; } void main() { float a[] = [10,11,12,13,14,15,16,17,18,19,20]; //a[Range(2,5)]; writefln("a.slice(3) = ", a.slice(3) ); writefln("a.slice([1,4,2,0,7]) = ", a.slice([1,4,2,0,7]) ); writefln("a.slice(Range(2)) = ", a.slice(Range(2)) ); writefln("a.slice(Range(2,4)) = ", a.slice(Range(2,4)) ); writefln("a.slice(Range(2,4i)) = ", a.slice(Range(2,4i)) ); writefln("a.slice(Range(2,8,2)) = ", a.slice(Range(2,8,2)) ); writefln("a.slice(Range(2,null,2)) = ", a.slice(Range(2,null,2)) ); writefln("a.slice(Range(2,8,-2)) = ", a.slice(Range(8,2,-2)) ); writefln("a.slice(Range(8,0i,-2)) = ", a.slice(Range(8,0i,-2)) ); writefln("a.slice([Range(4,-1,-2),Range(5,10,2)]) = ", a.slice([Range(4,-1,-2),Range(5,10,2)])); C c = new C; c.m_arr = a; writefln(); writefln("c[3] = ", c[3] ); writefln("c[[1,4,2,0,7]] = ", c[[1,4,2,0,7]] ); writefln("c[Range(2)] = ", c[Range(2)] ); writefln("c[Range(2,4)] = ", c[Range(2,4)] ); writefln("c[Range(2,8,2)] = ", c[Range(2,8,2)] ); writefln("c[Range(2,null,2)] = ", c[Range(2,null,2)] ); writefln("c[Range(8,2,-2)] = ", c[Range(8,2,-2)] ); writefln(); writefln("Range(0,5).list = ", Range(0,5).list); writefln("Range(4,null,-1).list = ", Range(4,null,-1).list); writefln("Range(0,10,2).list = ", Range(0,10,2).list); writefln("Range(8,-1,-2).list = ", Range(8,-1,-2).list); writefln(); writef("foreach(i,Range(0,10,2)): "); foreach(i; Range(0,10,2)) { writef(i, ", "); } writefln(); writef("foreach(i,Range(8,-1,-2)): "); foreach(i; Range(8,-1,-2)) { writef(i, ", "); } writefln(); writef("foreach(i,Range(0,null,3)): "); foreach(i; Range(0,null,3)) { if (i>12) { writefln("..."); break; } writef(i, ", "); } }