[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

AltStyle によって変換されたページ (->オリジナル) /