_indexed_ iteration using opApply or range

Simen kjaeraas simen.kjaras at gmail.com
Sun Dec 12 12:15:00 PST 2010


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.

-- 
Simen


More information about the Digitalmars-d-learn mailing list