"Simple Implicit Lambda", by Suzi & Martelli
This commit is contained in:
parent
a63e791682
commit
2999ba93f7
|
@ -0,0 +1,159 @@
|
|||
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: Draft
|
||||
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.
|
||||
|
||||
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:
|
||||
|
Loading…
Reference in New Issue