[Python-checkins] python/nondist/peps pep-0309.txt,1.4,1.5
goodger at users.sourceforge.net
goodger at users.sourceforge.net
Sat Feb 28 14:09:32 EST 2004
Update of /cvsroot/python/python/nondist/peps
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5776
Modified Files:
pep-0309.txt
Log Message:
update from Peter Harris
Index: pep-0309.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/peps/pep-0309.txt,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** pep-0309.txt 21 Feb 2004 16:32:30 -0000 1.4
--- pep-0309.txt 28 Feb 2004 19:09:16 -0000 1.5
***************
*** 1,4 ****
PEP: 309
! Title: Function Currying
Version: $Revision$
Last-Modified: $Date$
--- 1,4 ----
PEP: 309
! Title: Partial Function Application
Version: $Revision$
Last-Modified: $Date$
***************
*** 9,13 ****
Created: 08-Feb-2003
Python-Version: 2.4
! Post-History: 10-Feb-2003, 27-Feb-2003
--- 9,13 ----
Created: 08-Feb-2003
Python-Version: 2.4
! Post-History: 10-Feb-2003, 27-Feb-2003, 22-Feb-2004
***************
*** 15,28 ****
========
! 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', 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.
--- 15,24 ----
========
! 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().
***************
*** 30,35 ****
==========
! Curried functions are useful as functional 'sections' or as convenient
! anonymous functions for use as callbacks.
In some functional languages, (e.g. Miranda) you can use an expression
--- 26,46 ----
==========
! In functional programming, function currying is a way of implementing
! 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::
!
! f x y z
!
! 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
! terms of partial application of arguments to another function can be
! both elegant and powerful, and in functional languages it is heavily
! used.
In some functional languages, (e.g. Miranda) you can use an expression
***************
*** 41,50 ****
thing when presented with a functor and less arguments than expected.
! 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 not to everyone's taste, to say the least.
! We need something better.
--- 52,63 ----
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.
! However, lambda syntax is not to everyone's taste, so say the least.
! Furthermore, Python's flexible parameter passing using both positional
! and keyword presents an opportunity to generalise the idea of partial
! application and do things that lambda cannot.
***************
*** 52,60 ****
=========
! 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__(*args, **kw):
--- 65,73 ----
=========
! Here is one way to do a create a callable with partially-applied
! arguments in Python. The implementation below is based on improvements
! provided by Scott David Daniels::
! class partial(object):
def __init__(*args, **kw):
***************
*** 70,91 ****
return self.fn(*(self.args + args), **d)
! 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.
! 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 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
! http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52549.
! Update: It seems likely that a standard library implementation would
! be in Python, and would have to prove its worth there before making
! it into the built-ins.
--- 83,125 ----
return self.fn(*(self.args + args), **d)
! (A recipe similar to this has been in the Python Cookbook for some
! time [1]_.)
! Note that when the object is called as though it were a function,
! positional arguments are appended to those provided to the
! constructor, and keyword arguments override and augment those provided
! to the constructor.
! 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,
! rather than defining a subclass, you can specialise classes by partial
! application of the arguments to the constructor.
!
! For example, ``partial(Tkinter.Label, fg='blue')`` makes Tkinter
! Labels that have a blue foreground by default.
!
! Here's a simple example that uses partial application to construct
! callbacks for Tkinter widgets on the fly::
!
! from Tkinter import Tk, Canvas, Button
! import sys
! from functional import partial
!
! 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.pack(side='left')
!
! win.mainloop()
***************
*** 93,98 ****
=========================
! I originally suggested the syntax ``fn@(*args, **kw)``, meaning the same
! as ``curry(fn, *args, **kw)``.
At least there are no backwards-compatibility issues because the @
--- 127,132 ----
=========================
! 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 @
***************
*** 104,134 ****
call it.
! (The only other connection I can see with curry is that @ looks a bit
! like a section through a mushroom pakora.)
!
!
! Examples of Use
! ---------------
!
! Using closures as callbacks with bound arguments::
!
! def handler(arg1, arg2, opt=0):
! #whatever...
!
! button1 = Button(window, text="Action A",
! command=handler@('A', '1'))
! button2 = Button(window, text="Action B",
! command=handler@('B', '2', opt=1))
!
! Convenience functions ::
!
! nextarg = sys.argv.pop@(0)
!
! It has not been well-received, so I withdraw this part of the
proposal.
! Feedback from comp.lang.python
! ==============================
Among the opinions voiced were the following (which I summarise):
--- 138,147 ----
call it.
! It has not been well-received, so I have withdrawn this part of the
proposal.
! Feedback from comp.lang.python and python-dev
! =============================================
Among the opinions voiced were the following (which I summarise):
***************
*** 136,140 ****
* Lambda is good enough.
! * The @ syntax is ugly (so far, unanimous).
* It's really a curry rather than a closure. There is an almost
--- 149,153 ----
* Lambda is good enough.
! * The @ syntax is ugly (unanimous).
* It's really a curry rather than a closure. There is an almost
***************
*** 145,148 ****
--- 158,164 ----
library.
+ * 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.
***************
*** 151,155 ****
composition).
! * For completeness, another curry class that appends curried arguments
after those supplied in the function call (maybe called
``rightcurry``) has been suggested.
--- 167,171 ----
composition).
! * For completeness, another object that appends partial arguments
after those supplied in the function call (maybe called
``rightcurry``) has been suggested.
***************
*** 161,170 ****
weird. We have dictionary, list and tuple literals neatly
differentiated by special punctuation -- a way of directly expressing
! curried function literals is not such a stretch. However, 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 curry rather than closure, so I have
! amended this PEP accordingly.
Carl Banks posted an implementation as a real functional closure::
--- 177,193 ----
weird. We have dictionary, list and tuple literals neatly
differentiated by special punctuation -- a way of directly expressing
! partially-applied function literals is not such a stretch. However,
! 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
! throughout: some incorrect references to 'curry' have been left in
! since that's where the discussion was at the time.
!
! Partially applying arguments from the right, or inserting arguments at
! arbitrary positions creates its own problems, but pending discovery of
! a good implementation and non-confusing semantics, I don't think it
! should be ruled out.
Carl Banks posted an implementation as a real functional closure::
***************
*** 177,185 ****
return call_fn
! which he assures me is more efficient. All you lose with this
! implementation is introspection and sub-classing. These are only
! marginal benefits and not worth a performance hit, so this would also
! do as a reference implementation of a built-in curry function rather
! than a built-in curry class.
I also coded the class in Pyrex::
--- 200,207 ----
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.
I also coded the class in Pyrex::
***************
*** 202,209 ****
return self.fn(*(self.args + args), **d)
! 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. 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.
--- 224,232 ----
return self.fn(*(self.args + args), **d)
! 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. 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.
***************
*** 211,223 ****
=======
! 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. Other functions that might belong there fall outside this PEP though.
! The @ syntax proposal is withdrawn.
--- 234,252 ----
=======
! I prefer that some means to partially-apply functions and other
! 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
! outside the scope of this PEP though.
! The @ syntax proposal has been withrawn.
!
!
! References
! ==========
!
! .. [1] http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52549
More information about the Python-checkins
mailing list