Special keyword argument lambda syntax

Beni Cherniavsky beni.cherniavsky at gmail.com
Fri Mar 13 15:49:17 CET 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