challenge #2: implement the varargs_reduce metafunction

Kevin Bealer kevinbealer at gmail.com
Tue Jan 23 10:57:36 PST 2007


== Quote from Andrei Alexandrescu (See Website for Email)
(SeeWebsiteForEmail at erdani.org)'s article
> My previous post defines max by availing itself of a metafunction called
> varargs_reduce. Your challenge is to define it. varargs_reduce takes an
> alias which it assumes is a function of two arguments, and it defines a
> vararg function that applies that alias repeatedly, similarly to the
> reduce primitive that is present in functional languages. Again, for
> background on functional reduce, see e.g.:
>
> http://www.joelonsoftware.com/items/2006/08/01.html
>
> Define varargs_reduce to deduce the result type properly, and to
> generate code as efficient as possible.
>
> Andrei

There is a really simple solution, but I'm not sure if it does the right thing
with respect to your wording above.  What exactly is meant by deducing the result
type properly?  Specifically, if the input types are different kinds of objects,
is the result expected to have the same type as a linear sequence of operations?

1. Can we assume the type conversions are non-cyclic?
2. Should we assume that the delegate looks like: T dg(T, T), or like: T dg(U, V)
3. If the signature is T dg(U, V), can we assume that type conversions are non-cyclic?

 Cyclic types: (requires more template logic than actually shown here)

  Rock add(Paper x, Scissors y);
  Paper add(Scissors x, Rock x);
  Scissors add(Rock x, Paper y);

 If this kind of stuff is permitted, the solution is possible but a lot messier.

// Simple solution:

import std.stdio;
import std.traits;

template reduce(D, E...) {
    ReturnType!(D) reduce(D dg, E v)
    {
        ReturnType!(D) rv;

        static if (E.length >= 1) {
            rv = v[0];

            foreach(i, a; v[1..$]) {
                rv = dg(rv, a);
            }
        }

        return rv;
    }
}

int main(char[][] args)
{
    int add(int a, int b)
    {
        return a + b;
    }

    double mul(double a, double b)
    {
        return a * b;
    }

    int x = reduce(& add, 101, 102, 103, 104);
    double y = reduce(& mul, .1, .2, .3, .4, .5);

    writefln("sum=%s prod=%s", x, y);

    return 0;
}



More information about the Digitalmars-d mailing list