Thread overview | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
April 06, 2011 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.. |
April 06, 2011 Re: Why doesn't curry work with multiple arguments? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | 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
|
April 06, 2011 Re: Why doesn't curry work with multiple arguments? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | 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. |
April 06, 2011 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.. |
April 06, 2011 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); } } } } |
April 06, 2011 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. |
April 06, 2011 Re: Why doesn't curry work with multiple arguments? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | 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 |
April 06, 2011 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(); } |
April 06, 2011 Re: Why doesn't curry work with multiple arguments? | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 4/6/11, bearophile <bearophileHUGS@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..
|
April 06, 2011 Re: Why doesn't curry work with multiple arguments? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | 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 |
Copyright © 1999-2021 by the D Language Foundation