PEP: 312 Title: Simple Implicit Lambda Version: $Revision$
Last-Modified: $Date$ Author: Roman Suzi <rnd@onego.ru>, Alex Martelli
<aleaxit@gmail.com> Status: Deferred Type: Standards Track Content-Type:
text/x-rst 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 \[1\]\_.

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 referents (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" \[2\]\_.

References
==========

.. \[1\] Guido van Rossum, Recommend accepting PEP 312 -- Simple
Implicit Lambda
https://mail.python.org/pipermail/python-dev/2005-June/054304.html

.. \[2\] Guido van Rossum, For review: PEP 308 - If-then-else expression
https://mail.python.org/pipermail/python-dev/2003-February/033178.html

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:
