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