www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - problem with the variadic template

reply baleog <maccarka yahoo.com> writes:
Hello
I want to write "map" function with the Common Lisp "mapcar" behaviour. But i
don't understand how to write one template for the N-argument delegate. 
This is how it works now:

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;
}

How can i improve the code?

Thank you
Jul 05 2008
next sibling parent "Koroskin Denis" <2korden gmail.com> writes:
On Sun, 06 Jul 2008 02:19:09 +0400, baleog <maccarka yahoo.com> wrote:

 Hello
 I want to write "map" function with the Common Lisp "mapcar" behaviour=
. =
 But i don't understand how to write one template for the N-argument  =
 delegate.
 This is how it works now:

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

 How can i improve the code?

 Thank you
There already exists a map function in D2, see std.algorithm = (http://www.digitalmars.com/d/2.0/phobos/std_algorithm.html), take a loo= p = at it.
Jul 05 2008
prev sibling parent reply baleog <maccarka yahoo.com> writes:
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.
Jul 05 2008
parent "Koroskin Denis" <2korden gmail.com> writes:
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 =3D xs.length; foreach (i,x; xs) { result[i] =3D fun(x); } return result; } T[] map(T,T1,T2)(T delegate(T1, T2) fun, T1[] xs, T2[] ys) { T[] result; result.length =3D reduce!(min)(xs.length,[ys.length]); for (int i =3D 0; i<result.length; ++i) { result[i] =3D 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 =3D=3D 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 =3D args[0].length; // you may also put an assert to ens= ure = args lengths are same result.length =3D length; // preallocate memory for (int i =3D 0; i < length; ++i) { // now tricky part: we need extract data from args as a TT TT tt =3D 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] =3D arg[i]; } // invoke the function and store result result[i] =3D 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 :)
Jul 05 2008