In functional programming, currying is a way to bind arguments with a function and wait for the rest of the arguments to show up later. You "curry in" the first few parameters to a function, giving you a function that takes subsequent parameters as input and calls the original with all of those parameters. This recipe uses a class instance to hold the parameters before their first use. For example:
double = curry(operator.mul, 2)
triple = curry(operator.mul, 3)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class curry:
def __init__(self, fun, *args, **kwargs):
self.fun = fun
self.pending = args[:]
self.kwargs = kwargs.copy()
def __call__(self, *args, **kwargs):
if kwargs and self.kwargs:
kw = self.kwargs.copy()
kw.update(kwargs)
else:
kw = kwargs or self.kwargs
return self.fun(*(self.pending + args), **kw)
|
A typical use of curry is to construct callback functions for GUI operations. When the operation does not really merit a new function name, curry can be useful in creating these little functions. This can be the case with commands for buttons, for example.
self.button = Button(frame, text='A', command=curry(transcript.append, 'A'))
Curry can also be used interactively by making versions of your functions with debugging-appropriate defaults or initial parameters filled in for your current case. For example, database debugging work might well begin by setting:
Connect = curry(ODBC.Connect, dsn='MyDataSet')
If you are creating a function for regular use, and there is a good choice for a name, the 'def fun(...' form of function definition is usually more readable, and often more easily extended. As you can see from the implementation, no magic happens to "specialize" the function with the provided parameters; curry should be used when you feel the code is more clear with its use than without. Typically this will be to emphasize that you are only providing parameters to a "commonly used" (in this application) function, not providing separate processing.
'Lightweight' subclasses. This also works very well for creating a sort of lightwieght subclass..
ie. you can curry the constructor of a class to give the illusion of a subclass as follows:
bluewindow = curry(window, bg='blue')
bw = bluewindow()
..of course type(bluewindow) is still type(window), ( not a sub-type )
Additional parameters can still be passed to the curried constructor:
bw2 = bluewindow( title='blah', fg='yellow')
curry is cool, and not just for callbacks!
curry-by-closure. Lexically nested scopes (in Python 2.2 -- "from __future__ import" if you want to use them in 2.1) allow interesting currying too, e.g.:
This curries positional arguments from the right, and gives named arguments specified at call-time precedence over those specified at currying-time, but these policies are clearly easy to alter:-).
_Without_ nested scopes, I don't think it can be done with this level of generality (injecting names into the inner scope becomes hard to do generally when one wants fully-general args and *kwds...:-).
Alex
Using curry to wrap debugging information around calls. The 'curry' function can be used in debugging as well. For example, we can "wrap" method calls in objects:
alternative curry-by-closure. Nick Perkins' latest version of curry-by-closure (from c.l.p, for the record) is more general (no named args at all, thus no accidental name capture -- except, I think, for args and create_time_kwds...) and quite readable, although marginally more verbose, due to good name choices for intermediate locals. It also has curry-from-left (for positional args) and call-time-dominates (for named args) semantics, which may be popular:
Enhancement: the original function's __doc__ string... Why not also add this before returning the curried function:
This isn't currying. The operation performed by the operator described here is actually called "Partial Application". A good definition of currying can be inferred from http://tinyurl.com/3d6w6 and http://tinyurl.com/ly29.
Several languages have misused the term "curry" this way
Currying transforms a function taking a single tuple argument into a function taking multiple arguments, and uncurrying reverses the process.
Current curry code. I'd eliminate some micro-optimizations today and avoid spurious copies. Also, to allow named parameters such as 'self' to be specified in keywords, _no_ directly named args are provided.
The above works back through _many_ versions of python (though you might have to use "apply" to call self.fun if your Python is old). "Nested scopes" became a feature after this code was written. If I were to write it now, I might write:
Finally, putting the micro-optimizations (and one new one) back in:
Warning: special case. Change needed above. In the code above, bonono recently pointed out that instancemethod will not do what I want with a value of None, so the code above should be changed from:
to:
Curryng methods. I've found that using the closure you cannot apply curry to instance methods and classmethods using:
However with the addition of the decorator protocol to the class based implementation
perhaps it could be done better but it works (even with classmethod)
Python 2.5+ has a function in the standard library to do this. See http://docs.python.org/library/functools.html#functools.partial