On Wednesday, 1 April 2015 at 17:57:12 UTC, Dzugaru wrote:
Following recent IRC discussion.

I want to write a generic list aggregate function that works with builtin types like int[] as well as custom classes/structs that define front, empty, popFront:

import std.range;

ElementType!S aggregate(alias func, S)(S list, ElementType!S accum = ElementType!S.init)
if(is(typeof(func(accum, accum)) == typeof(accum))) {   
    foreach(ref e; list) {
        accum = func(accum, e);
    }
    return accum;       
}

Now I use it:

auto min1 = aggregate!((a, b) { return a < b ? a : b; }, int[])([2,4,1,3,5], int.max); auto min2 = aggregate!((a, b) { return a < b ? a : b; }, MyRange)(new MyRange(), int.max);

That works ok.

Now I don't want to specify template argument S, it can be deduced from the function call, right?

auto min1 = aggregate!((a, b) { return a < b ? a : b; })([2,4,1,3,5], int.max);

Doesn't work! "Error: template math.aggregate cannot deduce function from argument types..."

Now try this:
//No second parameter - leave it to be default
auto sum = aggregate!((a,  b) { return a + b; })([2,4,1,3,5]);

And it deduces S just fine.

a)
isn't this almost, if not exactly, the same as std.algorithm.reduce?

b)
you can write nice things like this:
auto min = [2,4,1,3,5].aggregate!((a, b) => a < b ? a : b)(int.max);

c)
the deduction failure looks like a bug to me, perhaps there is a good reason why it can't work in the general case.

Reply via email to