| 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
Permalink
Reply