The future of foreach| arbitrary number of arrays version

bearophile bearophileHUGS at lycos.com
Sun Dec 23 07:16:46 PST 2007


downs Wrote:
> Finally. This took entirely too long.

I am developing a large functional lib too ;-) I'll add something like this too (I already have two zip-like thingies there, but they aren't lazy).

This is my first try at a solution, but it has a bug still, the index i gives problems still (in your original 2-element solution too, I think). If you want you can fix the problem.

import std.stdio;
static import std.metastrings;

/// Like ArrayType, but it goes down just 1 level.
template ArrayType1(T: T[]) {
    alias T ArrayType1;
}

/// ...
template Lets2(string txt, int n) {
    static if (n > 0)
        const Lets2 = Lets2!(txt, n-1) ~
                      std.metastrings.Format!(txt,
                                              std.metastrings.ToString!(n-1),
                                              std.metastrings.ToString!(n-1));
    else
        const Lets2 = "";
}

// ------------------------------------

template SeriesGen1S(string txt, string separator, int max, int min=0) {
    static if (min > max)
        const SeriesGen1S = "";
    else static if (min == max)
        const SeriesGen1S = std.metastrings.Format!(txt, std.metastrings.ToString!(max));
    else
        const SeriesGen1S = SeriesGen1S!(txt, separator, max-1, min) ~ separator ~
                            std.metastrings.Format!(txt, std.metastrings.ToString!(max));
}

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

    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(size_t id, " ~ 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;
    }
    ");
}

_xzip!(TyArrays) xzip(TyArrays...)(TyArrays 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;
}

void main() {
    foreach (x, y; xzip([1, 2, 3, 4], [4.1, 5.1, 6.1]))
        writefln(x, " - ", y);
    writefln();

    foreach (x, y, z; xzip([1, 2, 3, 4], [4.1, 5.1, 6.1], "abcd"))
        writefln(x, " - ", y, " - ", z);

    //foreach (i, x, y; xzip([1, 2, 3, 4], [4.1, 5.1, 6.1])) // BUG
    //    writefln(i, ": ", x, " - ", y);
}


Bye,
bearophile



More information about the Digitalmars-d mailing list