_indexed_ iteration using opApply or range

Jonathan M Davis jmdavisProg at gmx.com
Sun Dec 12 12:32:23 PST 2010


On Sunday 12 December 2010 12:15:00 Simen kjaeraas wrote:
> spir <denis.spir at 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


More information about the Digitalmars-d-learn mailing list