186 lines
5.8 KiB
Plaintext
186 lines
5.8 KiB
Plaintext
PEP: 312
|
||
Title: Simple Implicit Lambda
|
||
Version: $Revision$
|
||
Last-Modified: $Date$
|
||
Author: Roman Suzi <rnd at onego.ru>, Alex Martelli <aleax at aleax.it>
|
||
Status: Deferred
|
||
Type: Standards Track
|
||
Content-Type: text/plain
|
||
Created: 11-Feb-2003
|
||
Python-Version: 2.4
|
||
Post-History:
|
||
|
||
|
||
Abstract
|
||
|
||
This PEP proposes to make argumentless lambda keyword optional in
|
||
some cases where it is not grammatically ambiguous.
|
||
|
||
Deferral
|
||
|
||
The BDFL hates the unary colon syntax. This PEP needs to go back
|
||
to the drawing board and find a more Pythonic syntax (perhaps an
|
||
alternative unary operator). See python-dev discussion on
|
||
17 June 2005.
|
||
|
||
Also, it is probably a good idea to eliminate the alternative
|
||
propositions which have no chance at all. The examples section
|
||
is good and highlights the readability improvements. It would
|
||
carry more weight with additional examples and with real-world
|
||
referrents (instead of the abstracted dummy calls to :A and :B).
|
||
|
||
Motivation
|
||
|
||
Lambdas are useful for defining anonymous functions, e.g. for use
|
||
as callbacks or (pseudo)-lazy evaluation schemes. Often, lambdas
|
||
are not used when they would be appropriate, just because the
|
||
keyword "lambda" makes code look complex. Omitting lambda in some
|
||
special cases is possible, with small and backwards compatible
|
||
changes to the grammar, and provides a cheap cure against such
|
||
"lambdaphobia".
|
||
|
||
|
||
Rationale
|
||
|
||
Sometimes people do not use lambdas because they fear to introduce
|
||
a term with a theory behind it. This proposal makes introducing
|
||
argumentless lambdas easier, by omitting the "lambda" keyword.
|
||
itself. Implementation can be done simply changing grammar so it
|
||
lets the "lambda" keyword be implied in a few well-known cases.
|
||
In particular, adding surrounding brackets lets you specify
|
||
nullary lambda anywhere.
|
||
|
||
|
||
Syntax
|
||
|
||
An argumentless "lambda" keyword can be omitted in the following
|
||
cases:
|
||
|
||
* immediately after "=" in named parameter assignment or default
|
||
value assignment;
|
||
|
||
* immediately after "(" in any expression;
|
||
|
||
* immediately after a "," in a function argument list;
|
||
|
||
* immediately after a ":" in a dictionary literal; (not
|
||
implemented)
|
||
|
||
* in an assignment statement; (not implemented)
|
||
|
||
|
||
Examples of Use
|
||
|
||
1) Inline "if":
|
||
|
||
def ifelse(cond, true_part, false_part):
|
||
if cond:
|
||
return true_part()
|
||
else:
|
||
return false_part()
|
||
|
||
# old syntax:
|
||
print ifelse(a < b, lambda:A, lambda:B)
|
||
|
||
# new syntax:
|
||
print ifelse(a < b, :A, :B)
|
||
|
||
# parts A and B may require extensive processing, as in:
|
||
print ifelse(a < b, :ext_proc1(A), :ext_proc2(B))
|
||
|
||
2) Locking:
|
||
|
||
def with(alock, acallable):
|
||
alock.acquire()
|
||
try:
|
||
acallable()
|
||
finally:
|
||
alock.release()
|
||
|
||
with(mylock, :x(y(), 23, z(), 'foo'))
|
||
|
||
|
||
Implementation
|
||
|
||
Implementation requires some tweaking of the Grammar/Grammar file
|
||
in the Python sources, and some adjustment of
|
||
Modules/parsermodule.c to make syntactic and pragmatic changes.
|
||
|
||
(Some grammar/parser guru is needed to make a full
|
||
implementation.)
|
||
|
||
Here are the changes needed to Grammar to allow implicit lambda:
|
||
|
||
varargslist: (fpdef ['=' imptest] ',')* ('*' NAME [',' '**'
|
||
NAME] | '**' NAME) | fpdef ['=' imptest] (',' fpdef ['='
|
||
imptest])* [',']
|
||
|
||
imptest: test | implambdef
|
||
|
||
atom: '(' [imptestlist] ')' | '[' [listmaker] ']' |
|
||
'{' [dictmaker] '}' | '`' testlist1 '`' | NAME | NUMBER | STRING+
|
||
|
||
implambdef: ':' test
|
||
|
||
imptestlist: imptest (',' imptest)* [',']
|
||
|
||
argument: [test '='] imptest
|
||
|
||
Three new non-terminals are needed: imptest for the place where
|
||
implicit lambda may occur, implambdef for the implicit lambda
|
||
definition itself, imptestlist for a place where imptest's may
|
||
occur.
|
||
|
||
This implementation is not complete. First, because some files in
|
||
Parser module need to be updated. Second, some additional places
|
||
aren't implemented, see Syntax section above.
|
||
|
||
|
||
Discussion
|
||
|
||
This feature is not a high-visibility one (the only novel part is
|
||
the absence of lambda). The feature is intended to make null-ary
|
||
lambdas more appealing syntactically, to provide lazy evaluation
|
||
of expressions in some simple cases. This proposal is not targeted
|
||
at more advanced cases (demanding arguments for the lambda).
|
||
|
||
There is an alternative proposition for implicit lambda: implicit
|
||
lambda with unused arguments. In this case the function defined by
|
||
such lambda can accept any parameters, i.e. be equivalent to:
|
||
lambda *args: expr. This form would be more powerful. Grep in the
|
||
standard library revealed that such lambdas are indeed in use.
|
||
|
||
One more extension can provide a way to have a list of parameters
|
||
passed to a function defined by implicit lambda. However, such
|
||
parameters need some special name to be accessed and are unlikely
|
||
to be included in the language. Possible local names for such
|
||
parameters are: _, __args__, __. For example:
|
||
|
||
reduce(:_[0] + _[1], [1,2,3], 0)
|
||
reduce(:__[0] + __[1], [1,2,3], 0)
|
||
reduce(:__args__[0] + __args__[1], [1,2,3], 0)
|
||
|
||
These forms do not look very nice, and in the PEP author's opinion
|
||
do not justify the removal of the lambda keyword in such cases.
|
||
|
||
|
||
Credits
|
||
|
||
The idea of dropping lambda was first coined by Paul Rubin at 08
|
||
Feb 2003 16:39:30 -0800 in comp.lang.python while discussing the
|
||
thread "For review: PEP 308 - If-then-else expression".
|
||
|
||
|
||
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:
|