Special keyword argument lambda syntax

B

Beni Cherniavsky

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::
[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?
 
B

Beni Cherniavsky

BeniCherniavsky said:
 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.

-1 from me.

I think thatlambda/ inline functions should be discouraged as it
moves python away from, "there should be one-- and preferably only one
--obvious way to do it."  IMHO Guido was right in his original impulse
to kill this second class way of making functions...
On a second thought, considering the LL(1) problem (which indicates a
real problem for humans parsing it) and the "f(x)==" confusion, I
agree.

Given that ``lambda`` usage is negligible compared to ``def`` (1.5% in
python3.0 stdlib, ~3% counting most Python files in ubuntu
repository), it should have been killed altogether per YAGNI and the
"one way" principle.

[Or is it just my "if you don't do it my way, don't do it at all"
emotion talking? Don't know. But I did the statistics only after
formulating the proposal, and I think now that 3% is definitely
YAGNI.]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top