problem with the variadic template

Koroskin Denis 2korden at gmail.com
Sat Jul 5 16:23:58 PDT 2008


On Sun, 06 Jul 2008 02:38:35 +0400, baleog <maccarka at 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 :)



More information about the Digitalmars-d mailing list