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.

--
Simen

Reply via email to