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.
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?
On 4/6/11, bearophile 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?
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?
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?
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?
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?
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?
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?
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
Why doesn't curry work with multiple arguments?
import std.functional; void foo(int x, int y, int z) { } alias curry!(foo, 1, 2, 3) bar; Error: template instance curry!(foo,1,2,3) does not match template declaration curry(alias fun,alias arg) Shouldn't curry take a variable number of arguments and then check the length of the arguments passed in against `fun`s length of parameters, and do its work from there? I'm trying to translate a C header file from the following to a D equivalent: #define txmOpenFile(hwndTV, szFile) \ SendMessage((hwndTV), TXM_OPENFILE, 0, (LPARAM)(szFile)) Yes, I write a whole new function, but why do that when curry is there. Or so I thought..