You must declare the
fun
template parameter as analias
parameter, otherwise it is declared as a type parameter:auto zipWith(alias fun, Ranges...)( // ...
You need to import
std.algorithm
formap
.std.range.zip
will return a range ofstd.typecons.Tuple
, which will not automatically expand into your lambda's two parameters. You need to expand the tuple explicitly.
Fixed code:
import std.traits: allSatisfy;
import std.range: isInputRange;
import std.algorithm: map;
auto zipWith(alias fun, Ranges...)(Ranges ranges) if (Ranges.length >= 2 && allSatisfy!(isInputRange, Ranges))
{
import std.range: zip;
return zip(ranges).map!(t => fun(t.expand));
}
unittest
{
auto x = [1, 2, 3, 4, 5];
zipWith!((a, b) => a + b)(x, x);
}
Is it possible to extend it to support nary fun's via strings, like
zipWith!"a+b+c"(x,x,x)
?
I don't see why not:
import std.string;
private string genNaryFun(string fun, V...)()
{
string code;
foreach (n, v; V)
code ~= "alias values[%d] %s;".format(n, cast(char)('a'+n));
code ~= "return " ~ fun ~ ";";
return code;
}
template naryFun(string fun)
{
auto naryFun(V...)(V values)
{
mixin(genNaryFun!(fun, V));
}
}
unittest
{
alias naryFun!"a + b + c" test;
assert(test(1, 2, 3) == 6);
}