July 05, 2008
Koroskin Denis Wrote:

> There already exists a map function in D2, see std.algorithm (http://www.digitalmars.com/d/2.0/phobos/std_algorithm.html), take a loop at it.
Standard map works only with string mixin (not with the delegate)  and multiple arrays it concatenates into 1. So std map mixin 1-argument function.
July 05, 2008
On Sun, 06 Jul 2008 02:38:35 +0400, baleog <maccarka@yahoo.com> wrote:

> Koroskin Denis Wrote:
>
>> There already exists a map function in D2, see std.algorithm
>> (http://www.digitalmars.com/d/2.0/phobos/std_algorithm.html), take a loop
>> at it.
> Standard map works only with string mixin (not with the delegate)  and multiple arrays it concatenates into 1. So std map mixin 1-argument function.


Ok, let's generalize your solution slightly.

T[] map(T, T1)(T delegate(T1) fun, T1[] xs) {
  T[] result; result.length = xs.length;
  foreach (i,x; xs)
    {
      result[i] = fun(x);
    }
  return result;
}

T[] map(T,T1,T2)(T delegate(T1, T2) fun, T1[] xs, T2[] ys) {
  T[] result; result.length = reduce!(min)(xs.length,[ys.length]);
  for (int i = 0; i<result.length; ++i)
    {
      result[i] = fun(xs[i], ys[i]);
    }
  return result;
}

First, replace T1,T2,T3.... TN with a variadic template:

T[] map(T, TT...)(T delegate(TT) fun, ArgsType args) {
   // ...
}

Now what's the type of args? It's better seen by example:
TT              ArgsType
(int, int)      (int[], int[])
(char, long)    (char[], long[])

So, we need some template that would convert TT to ArgsType. And it's simple!

// convert T to T[]
template TArr(T) {
    alias T[] TArr;
}

// create a tuple
template S(T...) {
    alias T S;
}

// create tuple of type[] from tuple of type
template SA(T...) {
    static if (T.length == 1) {
        alias S!(TArr!(T[0])) SA;
    } else {
        alias S!(TArr!(T[0]), SA!(T[1..$])) SA;
    }
}

Now map's signature becomes like this:
T[] map(T, TT...)(T delegate(TT) fun, SA!(TT) args);

And the only thing left is an implementation:

T[] map(T, TT...)(T delegate(TT) fun, SA!(TT) args) {
    T[] result;
    int length = args[0].length; // you may also put an assert to ensure args lengths are same
    result.length = length;	 // preallocate memory

    for (int i = 0; i < length; ++i) {
        // now tricky part: we need extract data from args as a TT
        TT tt = void;
        // there should really be a more simple approach, but I found none, so let's fill the tuple it by hand:
        foreach (j, arg; args) {
            tt[j] = arg[i];
        }

        // invoke the function and store result
        result[i] = fun(tt);
    }

    return result;
}

It works with both D1 and D2, but there is a problem - IFTI doesn't work anymore :(
P.S. Public domain, of course :)