Partially evaluated functions

Alex Martelli aleaxit at yahoo.com
Thu Jun 21 08:16:56 CEST 2001


"Nick Perkins" <nperkins7 at home.com> wrote in message
news:AVdY6.301331$eK2.61274820 at news4.rdc1.on.home.com...
    ...
> I used the following:
> ( supplies args left-to-right, with call-time kw args trumping create-time
> kw args )

But you do need a copy then, i.e.:

> from __future__ import nested_scopes
>
> def curry(func, *args, **kwds):
>     def curried_function(*moreargs, **morekwds):
>         kwds.update(morekwds)
>         return func(*(args+moreargs), **kwds)
>     return curried_function

Now if we try:

def f(**kw):
    for k,v in kw.items():
        print "%s->%s "%(k,v),
    print

cf = curry(f,be='bop')
cf(fee='fie')
cf(foo='fum')

we get:

fee->fie  be->bop
fee->fie  foo->fum  be->bop

I.e.,  now cf has unwanted state.  So the copy is needed.

def curry(func, *args, **kwds):
    def curried_function(*moreargs, **morekwds):
        kw = kwds.copy()
        kw.update(morekwds)
        return func(*(args+moreargs), **kw)
    return curried_function

Now, cf doesn't "accumulate" any more.  Still, this class:

> class curry_class:
>      def __init__(self, func, *args, **kwds):
>          self.func = func
>          self.args = args
>          self.kwds = kwds
>      def __call__(self, *moreargs, **morekwds):
>          self.kwds.update(morekwds)
>          return self.func(*(self.args + moreargs), **self.kwds)

has the same issue, I think.  The copy isn't needed for the
version where curry-time keywords take precedence, but if
call-time ones must override, then I think that copy we must.

> I found that the function-version is significantly faster than the
> class-version, in fact, almost twice as fast in the tests that I ran.
>
> Cool stuff.  Nested scopes rule.

For the functional-flavoured stuff they're designed to do, it
appears that they definitely shine.


Alex






More information about the Python-list mailing list