update from Peter Harris
This commit is contained in:
parent
fd32ea201c
commit
66588e0862
52
pep-0309.txt
52
pep-0309.txt
|
@ -1,5 +1,5 @@
|
|||
PEP: 309
|
||||
Title: Built-in Curry Type
|
||||
Title: Function Currying
|
||||
Version: $Revision$
|
||||
Last-Modified: $Date$
|
||||
Author: Peter Harris <scav@blueyonder.co.uk>
|
||||
|
@ -14,13 +14,13 @@ Post-History: 10-Feb-2003, 27-Feb-2003
|
|||
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
|
||||
partial argument list (including positional and keyword arguments).
|
||||
|
||||
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
|
||||
terminology has been amended since the first version of this PEP.
|
||||
accurate term for this is a 'curry', so the terminology has been
|
||||
amended since the first version of this PEP.
|
||||
|
||||
I propose a standard library module called "functional", to hold useful
|
||||
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
|
||||
thing when presented with a functor and less arguments than expected.
|
||||
|
||||
Python has more flexible argument-passing, and so curries cannot be
|
||||
implicit in the same way. Instead of using them, a Python programmer
|
||||
Python has more flexible argument-passing, and so function currying cannot
|
||||
be implicit in the same way. Instead, a Python programmer
|
||||
will probably either define another named function or use a lambda.
|
||||
But lambda syntax is horrible, especially when you want to do
|
||||
something complex.
|
||||
But lambda syntax is not to everyone's taste, to say the least.
|
||||
|
||||
We need something better.
|
||||
|
||||
|
@ -52,22 +51,25 @@ We need something better.
|
|||
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):
|
||||
|
||||
def __init__(self, fn, *args, **kw):
|
||||
self.fn, self.args, self.kw = (fn, args, kw)
|
||||
def __init__(*args, **kw):
|
||||
self = args[0]
|
||||
self.fn, self.args, self.kw = (args[1], args[2:], kw)
|
||||
|
||||
def __call__(self, *args, **kw):
|
||||
if self.kw:
|
||||
if kw and self.kw:
|
||||
d = self.kw.copy()
|
||||
d.update(kw)
|
||||
else:
|
||||
d = kw
|
||||
d = kw or self.kw
|
||||
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
|
||||
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
|
||||
Label class, but with a blue foreground by default.
|
||||
|
||||
I think a built-in type called ``curry``, that behaves the same way
|
||||
but maybe implemented more efficiently, would be very useful.
|
||||
I think a built-in class called ``curry`` that behaves the same way
|
||||
would be very useful.
|
||||
|
||||
Update: a recipe almost exactly like this has been in the Python
|
||||
Cookbook for quite some time, at
|
||||
|
@ -122,7 +124,7 @@ Convenience functions ::
|
|||
|
||||
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.
|
||||
|
||||
|
||||
|
@ -201,27 +203,23 @@ I also coded the class in Pyrex::
|
|||
|
||||
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
|
||||
calls. Any C implementation will be unlikely to be much faster, so the
|
||||
case for a builtin coded in C is not very strong.
|
||||
|
||||
calls. For the same reason, a C implementation will be unlikely to be much
|
||||
faster, so the case for a built-in coded in C is not very strong.
|
||||
|
||||
|
||||
Summary
|
||||
=======
|
||||
|
||||
I prefer that curry should be a built-in, with the semantics as
|
||||
described, whether as a function or a class. However, it should do its
|
||||
apprenticeship in the standard library first.
|
||||
I prefer that some means to curry functions should be a built-in, with the
|
||||
semantics as described, whether as a function or a callable class. However,
|
||||
it should do its apprenticeship in the standard library first.
|
||||
|
||||
The standard library module ``functional`` should contain ``curry`` and
|
||||
``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.
|
||||
|
||||
Since this proposal is now much less ambitious, I'd like to aim for
|
||||
inclusion in Python 2.3.
|
||||
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
|
Loading…
Reference in New Issue