Thread overview
apply function to parameters
Aug 06, 2013
Jack Applegame
Aug 06, 2013
Jack Applegame
Aug 06, 2013
bearophile
Aug 06, 2013
Jack Applegame
Aug 06, 2013
Dicebot
Aug 06, 2013
Jack Applegame
Aug 10, 2013
Artur Skawina
Aug 06, 2013
bearophile
August 06, 2013
In C++11 we can write:

    template<class... Args>
    void somefunc(Args... args {
        ...
    }

    template<class T>
    T process(T p) {
        ...
    }

    template <class... Args>
    void foo(Args... args) {
        somefunc(process(args)...);
    }

Is there a simple way to do this in D?
August 06, 2013
In other words, I need something like this:

foo(magicTemplate!(f, a1, a2, a3...)) === foo(f(a1), f(a2), f(a3)...)
August 06, 2013
Jack Applegame:

> Is there a simple way to do this in D?

somefunc(process(args));

Bye,
bearophile
August 06, 2013
Jack Applegame:

> In other words, I need something like this:
>
> foo(magicTemplate!(f, a1, a2, a3...)) === foo(f(a1), f(a2), f(a3)...)

Sorry, your second post was not yet present and I misunderstood your question.

Take a look at std.typetuple.staticMap

Bye,
bearophile
August 06, 2013
On Tuesday, 6 August 2013 at 14:44:18 UTC, bearophile wrote:
> Take a look at std.typetuple.staticMap
staticMap works with types, and I don't know how it can help.

August 06, 2013
On Tuesday, 6 August 2013 at 15:51:28 UTC, Jack Applegame wrote:
> On Tuesday, 6 August 2013 at 14:44:18 UTC, bearophile wrote:
>> Take a look at std.typetuple.staticMap
> staticMap works with types, and I don't know how it can help.

Not really. Anything that can be provided to template argument list can be stored in TypeTuple and thus processed by staticMap. Name is very confusing here.
August 06, 2013
On Tuesday, 6 August 2013 at 16:03:07 UTC, Dicebot wrote:
> On Tuesday, 6 August 2013 at 15:51:28 UTC, Jack Applegame wrote:
>> On Tuesday, 6 August 2013 at 14:44:18 UTC, bearophile wrote:
>>> Take a look at std.typetuple.staticMap
>> staticMap works with types, and I don't know how it can help.
>
> Not really. Anything that can be provided to template argument list can be stored in TypeTuple and thus processed by staticMap. Name is very confusing here.
Yes. Types, literals and aliases. But this doesn't help.

I wrote very ugly, but working solution. I don't like it, but I can't invent something better. :(

auto apply(alias p, alias f, Args...)(Args args) {
    auto impl(uint num, Head, Tail...)(Head head, Tail tail) {
        static if(num == 0) return p(head, tail);
        else return impl!(num - 1)(tail, f(head));
    }
    return impl!(args.length)(args);
}

apply!(fun1, fun2)(arg1, arg2, ...) === fun1(fun2(arg1), fun2(arg2), ...)

offtop: Dicebot, do you speak russian?
August 10, 2013
On 08/06/13 18:03, Dicebot wrote:
> On Tuesday, 6 August 2013 at 15:51:28 UTC, Jack Applegame wrote:
>> On Tuesday, 6 August 2013 at 14:44:18 UTC, bearophile wrote:
>>> Take a look at std.typetuple.staticMap
>> staticMap works with types, and I don't know how it can help.
> 
> Not really. Anything that can be provided to template argument list can be stored in TypeTuple and thus processed by staticMap. Name is very confusing here.

The problem is more that staticMap requires a *template*, not a function. Another one is that doing it like that (ie storing the intermediate results in a tuple or struct) creates unnecessary copies -  which isn't really an issue for small PODs, because the compiler optimizes most of the overhead away, but can have a significant cost when handling types w/ nontrivial cpctors etc.

Anyway, there are several ways to do this in D. One example:

   void foo(Args...)(Args args) {
       mixin(evalExpMap!(q{ somefunc(%...); }, q{ process(%s) }, args));
         // == `somefunc(process(args[0]), process(args[1]), etc);`
   }

   // or

   void foo(Args...)(Args args) {
       auto result = mixin(evalExpMap!(q{ somefunc(%...) }, q{ process(%s) }, args));
       //...
   }

   // and the helper:

   template evalExpMap(string C, string F, A...) {
      enum evalExpMap = {
         import std.array, std.conv;
         string s, l;
         static if (is(typeof(A))) alias B = typeof(A);
                else               alias B = A;
         foreach (I, _; B) {
            auto r = replace( replace(F, "%s", A[I].stringof),
                                         "%d", to!string(I));
            l ~= (I?", ":"") ~ r;
            s ~=               r ~ ";\n";
         }
         return replace(replace(C, "%...;", s), "%...", l);
      }();
   }

Not as simple as the C++ equivalent. But not that much more complicated and *much* more powerful.

artur