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.