python-peps/pep-0309.txt

126 lines
3.5 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

PEP: 309
Title: Built-in Closure Type
Version: $Revision$
Last-Modified: $Date$
Author: Peter Harris <scav@blueyonder.co.uk>
Status: Draft
Type: Standards Track
Content-Type: text/x-rst
Created: 08-Feb-2003
Python-Version: 2.4
Post-History:
Abstract
=========
This proposal is for a built-in closure type for Python that allows a
new callable to be constructed from another callable and a partial
argument list (including positional and keyword arguments). A concise
syntax shorthand for closures is suggested (tentatively).
Motivation
===========
Closures 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
such as ``(+1)`` to mean the equivalent of Python's ``(lambda x: x +
1)``.
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 closures cannot be
implicit in the same way. Instead of using them, 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.
We need something better.
Rationale
==========
Here is one way to do closures in Python::
class closure(object):
def __init__(self, fn, *args, **kw):
self.fn, self.args, self.kw = (fn, args, kw)
def __call__(self, *args, **kw):
d = self.kw.copy()
d.update(kw)
return self.fn(*(self.args + args), **d)
Note that when the closure is called, positional arguments are
appended to those provided to the constructor, and keyword arguments
override and augment those provided to the constructor.
So ``closure(operator.add,1)`` is a bit like ``(lambda x: 1+x)``, and
``closure(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 ``closure``, that behaves the same way
but maybe implemented more efficiently, would be very useful.
Tentative Syntax Proposal
==========================
I know syntax proposals have the odds stacked against them, and
introducing new punctuation characters is frowned upon, but I think
closures are a sufficiently powerful abstraction to deserve it.
I propose the syntax ``fn@(*args,**kw)``, meaning the same as
``closure(fn,*args,**kw)``. I have no idea what havoc this would
wreak on the parser.
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
call it.
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)
Copyright
=========
This document has been placed in the public domain.
..
Local Variables:
mode: indented-text
indent-tabs-mode: nil
sentence-end-double-space: t
fill-column: 70
End: