PEP309 - built-in curry class (revisions)

Peter Harris scav at blueyonder.co.uk
Fri Feb 28 05:12:21 EST 2003


Carl Banks <imbosol-1046365979 at aerojockey.com> wrote in message news:<18s7a.35798$ep5.10090 at nwrddc02.gnilink.net>...
> Peter Harris wrote:
> > Before I upload another (less drastically ambitious) version of
> > PEP 309, I want to thrash out a few things.
> > 
> > Several people have said curry() belongs in the standard library
> > rather than as a built-in. If so, what should the module name be,
> > and what sort of other things might the module contain?
> > 
> > The PEP is for a built-in of course, but I would be delighted
> > with inclusion in the standard library too, so I would like to
> > make a constructive proposal for it.
> > 
> > How about the following?
> > 
> >    Module to be called "functional" (it can be a home for
> >    operations on higher-order functions in general.)
> 
> Good idea.

I was due one :/
> 
> 
> >    functional.curry() as a nested function.
> > 
> >    functional.Curry as a class, so those who want the
> >        introspection and sub-classing can have it.
> 
> I assume this module would be written in C?  Then there's not much
> point in having a separate curry as a nested function.  The nested
> function curry's main advantage over the Python class form is that
> it's easier to write, more straightforward (to me) to read, and
> faster.  The first two advantages won't matter in a standard module,
> and a class written in C will be faster than the closure.
> 

Well, not everything in the standard library is implemented in C. I
can see the performance argument, but on the other hand there is also
the benefit of everyone being able to see the source.

Speaking of C though, does anyone want to help out with that? I got
about half way by implementing the class in Pyrex. There was about a
2x speedup over the closure - not huge. However Pyrex doesn't make
very human-readable C, and I'm not confident that I could do much
more with it than tidy up the variable names.

If I can't come up with a good C implementation, I can't press for curry
as a built-in and ask everyone else to do the work for me! That's another
reason for my liking the standard library approach much more now.

> As for the contents of the module, even if a general curry that can
> pick and choose its arguments isn't a good idea, there should at least
> be a right curry along with a left curry, so you can do things like
> this (to return first item of a list):
> 
>     curryright(operator.getitem,0)
> 
> You cannot do this simple thing with just a left curry.
> 
OK, I was concerned about the worst case where there are some required
arguments and a variable number of others - right-currying is not so
useful there. But you are right, there are tons of functions with a
fixed number of arguments where it might come in handy.

If you wanted a general substitution like maybe:
   g = curryinsert(f,a,__,b__,opt=1)
then you have the problem of what special value to use as the '__'.
Obviously it has to be something you never want to curry into the
argument list of a function!

Maybe something horrible like this would do:

   class ArgPlaceHolder:
       pass

   class curryinsert:
       def __init__(self,fn, *args,**kwargs):
            self.fn=fn
            self.args=args
            self.kwargs=kwargs
            self.subst=[]
            for i,a in enumerate(args):
                if isinstance(a,ArgPlaceHolder): self.subst.append(i)
       def __call__(self,*a,**kw):
            largs=list(self.args)  # need to modify this so a tuple won't do
            for i,j in enumerate(self.subst):
                largs[j] = a[i]
            a=a[len(self.subst):]
            d=self.kwargs.copy()
            d.update(kw)
            return self.fn(*(tuple(largs)+ a),**d)

I hesitate to propose something that ugly, though.

Peter




More information about the Python-list mailing list