The future of foreach| arbitrary number of arrays version

bearophile bearophileHUGS at lycos.com
Sun Dec 23 11:30:49 PST 2007


downs:
> Yay! :D More functional for D is always good.

Some things are better functional, others are better not, IMHO.
If you try to follow the two last chapters of "The little Schemer" you learn when FP becomes just a good way to twist your brain.


> I think the problem is that arbitrary lazy zip over foreachable things
> requires the use of Stackthreads or similar to work, which adds a speed hit.

My code can be improved a bit to make it work when the first parameter is any iterable object too.


> Ugh. Thanks for making me experience what other people feel when they read my code ..

I know mixins aren't much readable... :o)


> Just kidding. Good work, even though I don't fully understand it yet :D

If you have questions just ask. And you want to look the whole functional lib ask. It's open source after all...


And this gives a better error message when you give a single array:

_Xzip!(TyArrays) xzip(TyArrays...)(TyArrays arrays) {
    static assert(TyArrays.length >= 2, "xzip() accepts only 2 or more arrays.");

    int lenmin = arrays[0].length;
    foreach(arr; arrays[1 .. $])
        if (arr.length < lenmin)
            lenmin = arr.length;

    mixin("auto iter = _Xzip!(TyArrays)(" ~
          SeriesGen1S!("arrays[%s]", ", ", TyArrays.length-1) ~
          ");");
    iter.len = lenmin;
    return iter;
}

private struct _Xzip(TyArrays...) {
    static assert(TyArrays.length >= 2, "_Xzip accepts only 2 or more arrays.");

    mixin( Lets2!("alias ArrayType1!(TyArrays[%s]) T%s;\n", TyArrays.length) );
    mixin( Lets2!("T%s[] a%s;\n", TyArrays.length) );
    int len = 0;

    static if (TyArrays.length >= 2) {
        mixin("
        int opApply(int delegate(" ~ SeriesGen1S!("ref T%s", ", ", TyArrays.length-1) ~ ") dg) {
            foreach (size_t id, entry; a0[0 .. len])" ~
                "if (auto res = dg(entry, "~ SeriesGen1S!("a%s[id]", ", ", TyArrays.length-1, 1) ~ "))
                    return res;
            return 0;
        }
        ");

        mixin("
        int opApply(int delegate(ref size_t, " ~ SeriesGen1S!("ref T%s", ", ", TyArrays.length-1) ~ ") dg) {
            foreach (size_t id, entry; a0[0 .. len])" ~
                "if (auto res = dg(id, entry, "~ SeriesGen1S!("a%s[id]", ", ", TyArrays.length-1, 1) ~ "))
                    return res;
            return 0;
        }
        ");
    }
}


Limitations:
- xzip([]), zip([],[]), etc don't work.
- it doesn't work on a single array, like xzip([1, 2, 3]).
- So far it only works on static and dynamic arrays (no AAs or iterable objects).

Bye,
bearophile



More information about the Digitalmars-d mailing list