Currying decorator in python
The below implementation is naive, google for "currying python" for more accurate examples.
def curry(x, argc=None): if argc is None: argc = x.func_code.co_argcount def p(*a): if len(a) == argc: return x(*a) def q(*b): return x(*(a + b)) return curry(q, argc - len(a)) return p@currydef myfun(a,b,c): print '%d-%d-%d' % (a,b,c)myfun(11,22,33)myfun(44,55)(66)myfun(77)(88)(99)
The source code for curry
in the toolz
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.
Many of the answers here fail to address the fact that a curried function should only take one argument.
A quote from Wikipedia:
In mathematics and computer science, currying is the technique of translating the evaluation of a function that takes multiple arguments (or a tuple of arguments) into evaluating a sequence of functions, each with a single argument (partial application).
Choosing to decorate it with recursion and without co_argcount
makes for a decently elegant solution.
from functools import partial, wraps, reducedef curry(f): @wraps(f) def _(arg): try: return f(arg) except TypeError: return curry(wraps(f)(partial(f, arg))) return _def uncurry(f): @wraps(f) def _(*args): return reduce(lambda x, y: x(y), args, f) return _
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 of curry
. The true inverse in this case would actually be something like unwrap
, but it would require curry
to use functools.wraps
or something similar that sets a __wrapped__
attribute for each newly created function:
def unwrap(f): try: return unwrap(f.__wrapped__) except AttributeError: return f