Welcome, guest | Sign In | My Account | Store | Cart

this recipe defines two sets of functional-style curry and rcurry (right curry).

this is a compliment to: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52549

Python, 63 lines
 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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#---------------------------------------------------------------curry---
lcurry = lambda func, *args, **kw:\
            lambda *p, **n:\
                func(*args + p, **dict(kw.items() + n.items()))

# just for esthetics...
curry = lcurry


#--------------------------------------------------------------rcurry---
# NOTE: this adds the curried args to the tail...
rcurry = lambda func, *args, **kw:\
            lambda *p, **n:\
                func(*p + args, **dict(kw.items() + n.items()))


#--------------------------------------------------------------LCurry---
class LCurry(object):
    '''
    this is the left curry class.
    '''
    def __new__(cls, func, *args, **kw):
        obj = object.__new__(cls)
        if isinstance(func, LCurry) or isinstance(func, RCurry):
            obj._curry_func = func._curry_func
            obj._curry_args = (func._curry_args[0] + args, func._curry_args[1])
            obj._curry_kw = kw = kw.copy()
            kw.update(func._curry_kw)
        else:
            obj._curry_func = func
            obj._curry_args = (args, ())
            obj._curry_kw = kw.copy()
        return obj
    def __call__(self, *args, **kw):
        self._curry_func(*self._curry_args[0] + args + self._curry_args[1], **dict(self._curry_kw.items() + kw.items()))

# just for esthetics...
Curry = LCurry


#--------------------------------------------------------------RCurry---
class RCurry(object):
    '''
    this is the right curry class.
    '''
    def __new__(cls, func, *args, **kw):
        obj = object.__new__(cls)
        if isinstance(func, LCurry) or isinstance(func, RCurry):
            obj._curry_func = func._curry_func
            obj._curry_args = (func._curry_args[0] ,func._curry_args[1] + args)
            obj._curry_kw = kw = kw.copy()
            kw.update(func._curry_kw)
        else:
            obj._curry_func = func
            obj._curry_args = ((), args)
            obj._curry_kw = kw.copy()
        return obj
    def __call__(self, *args, **kw):
        self._curry_func(*self._curry_args[0] + args + self._curry_args[1], **dict(self._curry_kw.items() + kw.items()))



#-----------------------------------------------------------------------

<pre>most of the things said for the above mentioned recipe apply here as well, thus reading of that recipe is strongly recommended if you are not familiar with the curry concept and usage.

as for the reason there are two versions of each curry and rcurry see the note below.

here are a few examples:

---cut---

def f(*args): print args

here we use the lambda version...

ff = curry(f, 0)

now for what the classes are for...

fff0 = Curry(f, -1) fff1 = Curry(fff0, 0) fff2 = RCurry(fff1, 1)

print ff() # will print "(0,)" print fff0() # will print "(-1,)" print fff1() # will print "(-1, 0)" print fff2() # will print "(-1, 0, 1)" print fff2('foo') # will print "(-1, 0, 'foo', 1)"

--uncut--

NOTE: though the lambda version is faster and more memory efficient it does come at a cost, that is, if you use it recursively (as in the class example above) it will add an extra function call penalty for each recursion level when the resulting function is called. </pre>

Created by Alex Naanou on Tue, 16 Sep 2003 (PSF)
Python recipes (4591)
Alex Naanou's recipes (4)

Required Modules

  • (none specified)

Other Information and Tasks