I am trying to write a currying decorator in python, and I think I've got the general idea down, but still got some cases that aren't working right...
def curry(fun):
cache = []
numargs = fun.func_code.co_argcount
def new_fun(*args, **kwargs):
print args
print kwargs
cache.extend(list(args))
if len(cache) >= numargs: # easier to do it explicitly than with exceptions
temp = []
for _ in xrange(numargs):
temp.append(cache.pop())
fun(*temp)
return new_fun
@curry
def myfun(a,b):
print a,b
While for the following case this works fine:
myfun(5)
myfun(5)
For the following case it fails:
myfun(6)(7)
Any pointers on how to correctly do this would be greatly appreciated!
Thanks!
Many of the answers here fail to address the fact that a curried function should only take one argument.
A quote from Wikipedia:
Choosing to decorate it with recursion and without
co_argcount
makes for a decently elegant solution.As shown above, it is also fairly trivial to write an
uncurry
decorator. :) Unfortunately, the resulting uncurried function will allow any number of arguments instead of requiring a specific number of arguments, as may not be true of the original function, so it is not a true inverse ofcurry
. The true inverse in this case would actually be something likeunwrap
, but it would requirecurry
to usefunctools.wraps
or something similar that sets a__wrapped__
attribute for each newly created function:Here is my version of curry that doesn't use partial, and makes all the functions accept exactly one parameter:
The source code for
curry
in thetoolz
library is available at the following link.https://github.com/pytoolz/toolz/blob/master/toolz/functoolz.py
It handles args, kwargs, builtin functions, and error handling. It even wraps the docstrings back onto the curried object.