update from Peter Harris

This commit is contained in:
David Goodger 2004-02-21 16:32:30 +00:00
parent fd32ea201c
commit 66588e0862
1 changed files with 25 additions and 27 deletions

View File

@ -1,5 +1,5 @@
PEP: 309 PEP: 309
Title: Built-in Curry Type Title: Function Currying
Version: $Revision$ Version: $Revision$
Last-Modified: $Date$ Last-Modified: $Date$
Author: Peter Harris <scav@blueyonder.co.uk> Author: Peter Harris <scav@blueyonder.co.uk>
@ -14,13 +14,13 @@ Post-History: 10-Feb-2003, 27-Feb-2003
Abstract Abstract
======== ========
This proposal is for a standard curry type for Python that This proposal is for a curry constructor for Python that
allows a new callable to be constructed from a callable and a allows a new callable to be constructed from a callable and a
partial argument list (including positional and keyword arguments). partial argument list (including positional and keyword arguments).
Note: after feedback on comp.lang.python, I am persuaded that the most Note: after feedback on comp.lang.python, I am persuaded that the most
accurate term for this is a 'curry' rather than a 'closure', so the accurate term for this is a 'curry', so the terminology has been
terminology has been amended since the first version of this PEP. amended since the first version of this PEP.
I propose a standard library module called "functional", to hold useful I propose a standard library module called "functional", to hold useful
higher-order functions, including the curry() class. higher-order functions, including the curry() class.
@ -40,11 +40,10 @@ In general, languages like that are strongly typed, so the compiler
always knows the number of arguments expected and can do the right always knows the number of arguments expected and can do the right
thing when presented with a functor and less arguments than expected. thing when presented with a functor and less arguments than expected.
Python has more flexible argument-passing, and so curries cannot be Python has more flexible argument-passing, and so function currying cannot
implicit in the same way. Instead of using them, a Python programmer be implicit in the same way. Instead, a Python programmer
will probably either define another named function or use a lambda. will probably either define another named function or use a lambda.
But lambda syntax is horrible, especially when you want to do But lambda syntax is not to everyone's taste, to say the least.
something complex.
We need something better. We need something better.
@ -52,22 +51,25 @@ We need something better.
Rationale Rationale
========= =========
Here is one way to do a curry in Python:: Here is one way to do a create a curried callable in Python. The
implementation below is based on improvements provided by Scott David
Daniels::
class curry(object): class curry(object):
def __init__(self, fn, *args, **kw): def __init__(*args, **kw):
self.fn, self.args, self.kw = (fn, args, kw) self = args[0]
self.fn, self.args, self.kw = (args[1], args[2:], kw)
def __call__(self, *args, **kw): def __call__(self, *args, **kw):
if self.kw: if kw and self.kw:
d = self.kw.copy() d = self.kw.copy()
d.update(kw) d.update(kw)
else: else:
d = kw d = kw or self.kw
return self.fn(*(self.args + args), **d) return self.fn(*(self.args + args), **d)
Note that when the curry is called, positional arguments are Note that when the curried function is called, positional arguments are
appended to those provided to the constructor, and keyword arguments appended to those provided to the constructor, and keyword arguments
override and augment those provided to the constructor. override and augment those provided to the constructor.
@ -75,8 +77,8 @@ So ``curry(operator.add, 1)`` is a bit like ``(lambda x: 1 + x)``, and
``curry(Tkinter.Label, fg='blue')`` is a callable like the Tkinter ``curry(Tkinter.Label, fg='blue')`` is a callable like the Tkinter
Label class, but with a blue foreground by default. Label class, but with a blue foreground by default.
I think a built-in type called ``curry``, that behaves the same way I think a built-in class called ``curry`` that behaves the same way
but maybe implemented more efficiently, would be very useful. would be very useful.
Update: a recipe almost exactly like this has been in the Python Update: a recipe almost exactly like this has been in the Python
Cookbook for quite some time, at Cookbook for quite some time, at
@ -122,7 +124,7 @@ Convenience functions ::
nextarg = sys.argv.pop@(0) nextarg = sys.argv.pop@(0)
It has not been well-received, so I am not pursuing this as a serious It has not been well-received, so I withdraw this part of the
proposal. proposal.
@ -201,27 +203,23 @@ I also coded the class in Pyrex::
The performance gain in Pyrex is less than 100% over the nested function The performance gain in Pyrex is less than 100% over the nested function
implementation, since to be fully general it has to operate by Python API implementation, since to be fully general it has to operate by Python API
calls. Any C implementation will be unlikely to be much faster, so the calls. For the same reason, a C implementation will be unlikely to be much
case for a builtin coded in C is not very strong. faster, so the case for a built-in coded in C is not very strong.
Summary Summary
======= =======
I prefer that curry should be a built-in, with the semantics as I prefer that some means to curry functions should be a built-in, with the
described, whether as a function or a class. However, it should do its semantics as described, whether as a function or a callable class. However,
apprenticeship in the standard library first. it should do its apprenticeship in the standard library first.
The standard library module ``functional`` should contain ``curry`` and The standard library module ``functional`` should contain ``curry`` and
``rightcurry`` classes, and any other higher-order functions the community ``rightcurry`` classes, and any other higher-order functions the community
want. These other functions fall outside this PEP though. want. Other functions that might belong there fall outside this PEP though.
The @ syntax proposal is withdrawn. The @ syntax proposal is withdrawn.
Since this proposal is now much less ambitious, I'd like to aim for
inclusion in Python 2.3.
Copyright Copyright
========= =========