Special keyword argument lambda syntax
Beni Cherniavsky
beni.cherniavsky at gmail.com
Fri Mar 13 10:49:17 EDT 2009
This proposal (a) ignores Guido's clear-cut decision that lambda is
good as it is, (b) is weird in proposing a special-case syntax, (c) is
several Python versions too late for a graceful transition by 3.0.
But I don't won't to just throw the idea away, so I'm posting here.
If there is serious positive feedback proving I'm not crazy, I'll make
a PEP.
Abstract
========
This proposal outrageously suggests a special syntax for in-line
functions passed as keyword arguments::
>>> sorted(range(9), key(n)=n%3)
[0, 3, 6, 1, 4, 7, 2, 5, 8]
The claim is that such specialization hits a syntax sweet spot, and
that this use case is frequent enough to contemplate eventually making
it the only in-line function syntax.
Specification
=============
Allow keyword arguments in function call to take this form:
NAME ( ARGUMENTS ) = EXPRESSION
which is equivallent to the following:
NAME = lambda ARGUMENTS: EXPRESSION
except that NAME is also assigned as the function's `__name__`.
Motivation
==========
``lambda`` is widely considered arbitrary and ugly, as proven by the
numerous proposals for alternative syntax. It's also widely
considered good enough, as proven by said proposals being consistently
shot down ;-).
The proposed syntax solves the following drawbacks of lambda:
- It's not obvious from the look of ``lambda n: n % 3`` that it
defines a function.
``key(n) = n % 3`` is arguably so clear intuitively, that it won't a
non-familiar
reader won't have to stop and look it up. (The ability to look
"lambda" up is
cited as one of the main reasons to keep it.)
- A long meaningless (for non-lisp-geeks) keyword in the middle of
code.
- The use of ``:`` to delimit the lambda body is misleading - people
expect
``:`` to be followed by a statement, not an expression.
- Lambda functions are anonymous, which makes their origin harder to
recognize when debugging. The proposed syntax allows the keyword
argument to also serve as the function name, giving a (somewhat)
meaningful name without any naming effort from the user.
However nice this syntax, why should we consider something targeted at
the special case of keyword arguments?
1. It is an important use case. Consider "lambda" usage in the 3.0
stdlib:
* 22 times (ab)used as stand-alone shorthand to ``def``.
* 18 times passed to `map()` / `filter()` - most are old code
predating list
comprehensions (given away by ``x=x`` hack predating nested
scopes).
* 4 times passed to `property()` - now better written as
``@property`` def.
* 25 times used as "legitimate" positional argument (not one of the
above).
* 31 times used as a keyword argument.
* 6 times used in other constructs.
So keyword cover about half of the good uses of lambda, and many
uses
as positional arguments can be converted to keyword arguments,
sometimes
improving readability (cf. 3.0's conversion of `key` and `reverse`
arguments
to keyword-only).
2. We don't have to cover *all* use cases - remember that one can
always fall
back on ``def`` (which BTW is used ~10250 times in stdlib, making
all uses
of lambda total 1% of uses of ``def``, making one wonder if we need
in-line
function syntax at all).
So one can imagine this syntax one day replacing most uses of
``lambda``, at which point ``lambda`` can be killed altogether.
Optional extension
=================
Given this syntax for keyword arguments, users might expect it to also
word as a standalone statement:
NAME ( ARGUMENTS ) = EXPRESSION
which is equivallent to the following:
def NAME ( ARGUMENTS):
return EXPRESSION
Should we allow it? People abuse ``lambda`` in this way already (see
above stdlib statistics), this is just a cleaner version. But this
syntax has no place for a docstring, so allowing it will encourage
people to write functions without docstings. Opinions anybody?
More information about the Python-list
mailing list