On Sunday 12 December 2010 12:15:00 Simen kjaeraas wrote: > spir <denis.s...@gmail.com> wrote: > > Hello, > > > > Had a nice time figuring out how to let opApply allow index iteration > > > > like: > > foreach (i, x ; collection) {} > > > > Finally managed to do it adding 'i' everywhere: > > > > struct S1 { > > > > private int[] elements = []; > > int opApply (int delegate (ref uint, ref int) block) { > > > > foreach (uint i, int n ; this.elements) > > > > block(i, n); > > > > return 0; > > > > } > > > > } > > > > Is this the intended idiom? > > opApply is a strange beast. Your version does not handle early returns > or other errors, for which block's return type should be checked: > > int opApply( int delegate( ref uint, ref int ) block ) { > foreach ( uint i, int n; this.elements ) { > if ( auto ret = block( i, n ) != 0 ) { > return ret; > } > } > return 0; > } > > As for the i, yes, you have to do it like that. In fact, you can have as > many parameters you want for the delegate, and refer to them in the > foreach: > > struct foo{ > int opApply( T... )( int delegate( ref T ) dg ) { > return 0; > } > } > > > foo f; > foreach ( int i, double d, string s; f ) {} > > > Now, I'm trying to make this work with ranges instead (input range only > > as of now). Seems i'm not smart enough to guess it alone... > > The trick to ranges is that they modify themselves. For a simple array > wrapper > range this may be a way: > > struct wrapper( T ) { > T[] data; > void popFront( ) { > data = data[1..$]; > } > ref T front( ) { > return data[0]; > } > bool empty( ) { > return data.length == 0; > } > } > > Feel free to ask if you wonder about anything specific.
I'd also point out that the correct type for indexing is generally size_t. That's what arrays use. I believe that size_t _is_ uint on 32 bit machines, but it's going to be ulong on 64 bit machines. So, using uint is not portable. - Jonathan M Davis