## digitalmars.D - problem with the variadic template

• baleog (21/21) Jul 05 2008 Hello
• Koroskin Denis (6/29) Jul 05 2008 There already exists a map function in D2, see std.algorithm =
• baleog (2/5) Jul 05 2008 Standard map works only with string mixin (not with the delegate) and m...
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
"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
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
"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