ActiveState Code

Recipe 363775: Curry


Suppose you have a function "sum(a, b)". This class lets you do things like:

plus4 = Curry(sum, 4)
print plus4(5)
Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
"""This class is a curry (think functional programming)."""

__docformat__ = "restructuredtext"


class Curry:

    """This class is a curry (think functional programming).

    The following attributes are used:

    f
      This is the function being curried.

    initArgs, initKargs
      These are the args and kargs to pass to ``f``.

    """

    def __init__(self, f, *initArgs, **initKargs):
        """Accept the initial arguments and the function."""
        self.f = f
        self.initArgs = initArgs
        self.initKargs = initKargs

    def __call__(self, *args, **kargs):
        """Call the function."""
        updatedArgs = self.initArgs + args
        updatedKargs = self.initKargs.copy()
        updatedKargs.update(kargs) 
        return self.f(*updatedArgs, **updatedKargs)

Discussion

In Python 2.3 or greater, it's easy to get this same functionality using a lambda acting as a closure.

Comments

  1. 1. At 10:53 a.m. on 20 jan 2005, Matt Good said:

    Xoltar Toolkit. Check out the Xoltar Toolkit at http://www.xoltar.org/languages/python.html

    The "functional" module has a better implementation of curry that allows you to do things like curry parameters out of order. The other methods in there are quite useful as well.

  2. 2. At 1:57 p.m. on 20 jan 2005, Scott David Daniels said:

    Matches recipe 52549. Remove any explicitly named parameters. I'm not sure how this differs much from:

    http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52549
    

    From the reactions I've had from that, I'd change the first few lines of each method to:

    class Curry:
        def __init__(*args, **initKargs):
            self = args[0]
            self.f = args[1]
            self.initArgs = args[2:]
            ...
        def __call__(*args, **kargs):
            self = args[0]
            updatedArgs = self.initArgs + args[1:]
            ...
    

    This allows keyword currying or providing of _all_ parameters as named parameters.

Sign in to comment