update from Peter Harris; minor edits
This commit is contained in:
parent
4957e14b72
commit
867839cff4
73
pep-0309.txt
73
pep-0309.txt
|
@ -1,5 +1,5 @@
|
|||
PEP: 309
|
||||
Title: Partial Function Application
|
||||
Title: Partial Function Application
|
||||
Version: $Revision$
|
||||
Last-Modified: $Date$
|
||||
Author: Peter Harris <scav@blueyonder.co.uk>
|
||||
|
@ -18,15 +18,18 @@ This proposal is for a function or callable class that allows a new
|
|||
callable to be constructed from a callable and a partial argument list
|
||||
(including positional and keyword arguments).
|
||||
|
||||
I propose a standard library module called "functional", to hold useful
|
||||
higher-order functions, including the implementation of partial().
|
||||
I propose a standard library module called "functional", to hold
|
||||
useful higher-order functions, including the implementation of
|
||||
partial().
|
||||
|
||||
An implementation has been submitted to SourceForge [2]_.
|
||||
|
||||
|
||||
Motivation
|
||||
==========
|
||||
|
||||
In functional programming, function currying is a way of implementing
|
||||
multi-argument functions in terms of single-argument functions. A
|
||||
multi-argument functions in terms of single-argument functions. A
|
||||
function with N arguments is really a function with 1 argument that
|
||||
returns another function taking (N-1) arguments. Function application
|
||||
in languages like Haskell and ML works such that a function call::
|
||||
|
@ -38,7 +41,7 @@ actually means::
|
|||
(((f x) y) z)
|
||||
|
||||
This would be only an obscure theoretical issue except that in actual
|
||||
programming it turns out to be very useful. Expressing a function in
|
||||
programming it turns out to be very useful. Expressing a function in
|
||||
terms of partial application of arguments to another function can be
|
||||
both elegant and powerful, and in functional languages it is heavily
|
||||
used.
|
||||
|
@ -52,8 +55,9 @@ always knows the number of arguments expected and can do the right
|
|||
thing when presented with a functor and less arguments than expected.
|
||||
|
||||
Python does not implement multi-argument functions by currying, so if
|
||||
you want a function with partially-applied arguments you would probably
|
||||
use a lambda as above, or define a named function for each instance.
|
||||
you want a function with partially-applied arguments you would
|
||||
probably use a lambda as above, or define a named function for each
|
||||
instance.
|
||||
|
||||
However, lambda syntax is not to everyone's taste, so say the least.
|
||||
Furthermore, Python's flexible parameter passing using both positional
|
||||
|
@ -61,11 +65,11 @@ and keyword presents an opportunity to generalise the idea of partial
|
|||
application and do things that lambda cannot.
|
||||
|
||||
|
||||
Rationale
|
||||
=========
|
||||
Example Implementation
|
||||
======================
|
||||
|
||||
Here is one way to do a create a callable with partially-applied
|
||||
arguments in Python. The implementation below is based on improvements
|
||||
arguments in Python. The implementation below is based on improvements
|
||||
provided by Scott David Daniels::
|
||||
|
||||
class partial(object):
|
||||
|
@ -90,6 +94,9 @@ positional arguments are appended to those provided to the
|
|||
constructor, and keyword arguments override and augment those provided
|
||||
to the constructor.
|
||||
|
||||
Positional arguments, keyword arguments or both can be supplied at
|
||||
when creating the object and when calling it.
|
||||
|
||||
|
||||
Examples of Use
|
||||
===============
|
||||
|
@ -97,8 +104,8 @@ Examples of Use
|
|||
So ``partial(operator.add, 1)`` is a bit like ``(lambda x: 1 + x)``.
|
||||
Not an example where you see the benefits, of course.
|
||||
|
||||
Note too, that you could wrap a class in the same way, since
|
||||
classes themselves are callable factories for objects. So in some cases,
|
||||
Note too, that you could wrap a class in the same way, since classes
|
||||
themselves are callable factories for objects. So in some cases,
|
||||
rather than defining a subclass, you can specialise classes by partial
|
||||
application of the arguments to the constructor.
|
||||
|
||||
|
@ -115,9 +122,10 @@ callbacks for Tkinter widgets on the fly::
|
|||
win = Tk()
|
||||
c = Canvas(win,width=200,height=50)
|
||||
c.pack()
|
||||
|
||||
|
||||
for colour in sys.argv[1:]:
|
||||
b = Button(win, text=colour, command=partial(c.config,bg=colour))
|
||||
b = Button(win, text=colour,
|
||||
command=partial(c.config, bg=colour))
|
||||
b.pack(side='left')
|
||||
|
||||
win.mainloop()
|
||||
|
@ -129,16 +137,13 @@ Abandoned Syntax Proposal
|
|||
I originally suggested the syntax ``fn@(*args, **kw)``, meaning the
|
||||
same as ``partial(fn, *args, **kw)``.
|
||||
|
||||
At least there are no backwards-compatibility issues because the @
|
||||
character isn't a legal operator in any previous versions of Python.
|
||||
|
||||
The @ sign is used in some assembly languages to imply register
|
||||
indirection, and the use here is also a kind of indirection.
|
||||
``f@(x)`` is not ``f(x)`` , but a thing that becomes ``f(x)`` when you
|
||||
``f@(x)`` is not ``f(x)``, but a thing that becomes ``f(x)`` when you
|
||||
call it.
|
||||
|
||||
It has not been well-received, so I have withdrawn this part of the
|
||||
proposal.
|
||||
It was not well-received, so I have withdrawn this part of the
|
||||
proposal. In any case, @ has been taken for the new decorator syntax.
|
||||
|
||||
|
||||
Feedback from comp.lang.python and python-dev
|
||||
|
@ -157,7 +162,7 @@ Among the opinions voiced were the following (which I summarise):
|
|||
* A curry class would indeed be a useful addition to the standard
|
||||
library.
|
||||
|
||||
* It isn't function currying, but partial application. Hence the
|
||||
* It isn't function currying, but partial application. Hence the
|
||||
name is now proposed to be partial().
|
||||
|
||||
* It maybe isn't useful enough to be in the built-ins.
|
||||
|
@ -181,7 +186,7 @@ not one single person has said they like it, so as far as I'm
|
|||
concerned it's a dead parrot.
|
||||
|
||||
I concur with calling the class partial rather than curry or closure,
|
||||
so I have amended the proposal in this PEP accordingly. But not
|
||||
so I have amended the proposal in this PEP accordingly. But not
|
||||
throughout: some incorrect references to 'curry' have been left in
|
||||
since that's where the discussion was at the time.
|
||||
|
||||
|
@ -199,12 +204,10 @@ Carl Banks posted an implementation as a real functional closure::
|
|||
return fn(*(cargs + fargs), **d)
|
||||
return call_fn
|
||||
|
||||
which he assures me is more efficient. You lose introspection and
|
||||
sub-classing that way, but these are maybe only marginal benefits and
|
||||
not worth a performance hit, so this would also do as a reference
|
||||
implementation.
|
||||
which he assures me is more efficient.
|
||||
|
||||
I also coded the class in Pyrex::
|
||||
I also coded the class in Pyrex, to estimate how the performance
|
||||
might be improved by coding it in C::
|
||||
|
||||
cdef class curry:
|
||||
|
||||
|
@ -238,10 +241,16 @@ callables should be present in the standard library.
|
|||
|
||||
A standard library module ``functional`` should contain an
|
||||
implementation of ``partial``, and any other higher-order functions
|
||||
the community want. Other functions that might belong there fall
|
||||
the community want. Other functions that might belong there fall
|
||||
outside the scope of this PEP though.
|
||||
|
||||
The @ syntax proposal has been withrawn.
|
||||
Patches for the implementation, documentation and unit tests (SF
|
||||
patches 931005_, 931007_, and 931010_ respectively) have been
|
||||
submitted but not yet checked in.
|
||||
|
||||
A C implementation by Hye-Shik Chang has also been submitted, although
|
||||
it is not expected to be included until after the Python
|
||||
implementation has proven itself useful enough to be worth optimising.
|
||||
|
||||
|
||||
References
|
||||
|
@ -249,6 +258,12 @@ References
|
|||
|
||||
.. [1] http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52549
|
||||
|
||||
.. [2] Patches 931005_, 931007_, and 931010_.
|
||||
|
||||
.. _931005: http://www.python.org/sf/931005
|
||||
.. _931007: http://www.python.org/sf/931007
|
||||
.. _931010: http://www.python.org/sf/931010
|
||||
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
|
Loading…
Reference in New Issue