Re: Why doesn't curry work with multiple arguments?
Andrej Mitrovic Wrote: Yes, I write a whole new function, but why do that when curry is there. Or so I thought.. Oops: *Yes, I _can_ write a whole new function
Re: Why doesn't curry work with multiple arguments?
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.
Re: Why doesn't curry work with multiple arguments?
Crap, that is a horrible implementation, I didn't take into account not binding all arguments. Be right back..
Re: Why doesn't curry work with multiple arguments?
Ok, enjoy this monstrosity: template count(T...) { enum count = T.length; } template myCurry(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)) { static if ((ParameterTypeTuple!fun).length - count!args) { ReturnType!fun myCurry(ParameterTypeTuple!fun[0 .. (ParameterTypeTuple!fun).length - count!args] myarg) { return fun(args, myarg); } } else { ReturnType!fun myCurry() { return fun(args); } } } }
Re: Why doesn't curry work with multiple arguments?
It's still wrong, the tuple is backwards. Haha, that's what I get for not unittesting.
Re: Why doesn't curry work with multiple arguments?
Andrej Mitrovic: Here's a basic implementation: I have some general comments: - Currying and partial function application are not exactly the same thing. So I am not sure the curry in std.functional is named correctly; - Partial application is important in a language that wants to support functional idioms a little. This means that if D doesn't currently supports Partial application well, then it's worth improving; - A good function application must be able to solve this little rosettacode task too: http://rosettacode.org/wiki/Partial_function_application Bye, bearophile
Re: Why doesn't curry work with multiple arguments?
Wow, talk about enlightement. I think I've done it now: import std.stdio; import std.traits; import std.metastrings; template count(T...) { enum count = T.length; } template myCurry(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)); } ReturnType!fun myCurry(T...)(T t) { return fun(args, t); } } void foo(string x, int y, int z) { writeln(x, y, z); } alias myCurry!(foo, bar) oneCurry; alias myCurry!(foo, bar, 1)twoCurry; alias myCurry!(foo, bar, 1, 2) threeCurry; void main() { oneCurry(1, 2); twoCurry(2); threeCurry(); }
Re: Why doesn't curry work with multiple arguments?
On 4/6/11, bearophile bearophileh...@lycos.com wrote: - Currying and partial function application are not exactly the same thing. So I am not sure the curry in std.functional is named correctly; Maybe bind should be a better name. I'm not sure..
Re: Why doesn't curry work with multiple arguments?
Andrej Mitrovic: Maybe bind should be a better name. I'm not sure.. In Python there is something similar that's named partial: http://docs.python.org/library/functools.html#functools.partial Bye, bearophile
Re: Why doesn't curry work with multiple arguments?
Well this still hasn't solved my problem. Because I shouldn't bind from left to right, but arbitrarily. So ideally I would want this: void foo(string str, int x, int y, string str2) { } alias bind!(foo, null, 1, 2, null) twoStrings; twoStrings(abc, def); - foo(abc, 1, 2, def); I'm pretty sure I could do this with D's templates.