Here's a basic implementation:
import std.stdio;
import std.traits;
import std.metastrings;
template count(T...)
{
enum count = T.length;
}
template curry(alias fun, args...)
{
static if (args.length > (ParameterTypeTuple!fun).length)
{
static assert(0, Format!("Tried to pass %s arguments, max is %s.",
count!args, (ParameterTypeTuple!fun).length));
}
static if (is(typeof(fun) == delegate) || is(typeof(fun) == function))
{
ReturnType!fun curry()
{
return fun(args);
}
}
}
void foo(int x, int y)
{
writeln(x, y);
}
alias curry!(foo, 1, 2) bar;
void main()
{
bar();
}
It will complain if you try to pass it more arguments than a function
can take. I didn't implement curry's original else clause because I
have no idea what's going on there (some comments would be useful in
Phobos implementations, people!......)
There is some wacky error if I didn't use the count template
workaround. If I try to use args.length twice, like so:
static if (args.length > (ParameterTypeTuple!fun).length)
{
static assert(0, Format!("Tried to pass %s arguments, max is %s.",
args.length, (ParameterTypeTuple!fun).length));
}
Then I get back: identifier 'length' of 'args.length' is not defined
But it only errors out in the static assert, and yet it can check
args.length in the static if. Really weird.