[Python-ideas] A simple proposal concerning lambda
Steven D'Aprano
steve at pearwood.info
Tue Aug 21 21:55:03 EDT 2018
On Tue, Aug 21, 2018 at 10:27:20PM +0100, Jonathan Fine wrote:
> Here is my simple proposal. Enhance Python to allow
>
> >>> hn = def a, b=2, c=3: a ** b / c
Enhancements ought to allow us to write new code that we couldn't do
before, or open up new kinds of algorithms that weren't easy or possible
before.
This is a mere cosmetic change, replacing a perfectly valid keyword with
one which clashes with an existing keyword in what I consider to be an
ugly way.
While we're at it, perhaps we ought to replace:
- "else" with "otherwise"
("else" is a weird word, outside of programming we hardly ever use it
without a leading "or")
- "import" with "load" (shorter)
- "for" with "repeat with"
(I've always found it awkward that the word "for" sounds like an number)
- "raise" with "throw"
- and most importantly, "def" with "fun", which will have the
advantage of making Python programming more fun!
Admittedly these run into backwards-compatibility issues, which your
suggestion does not. But if we're going to break people's code by
changing keywords, let's do it properly! *wink*
Changing the public API of a language, its keywords, is not something to
be done lightly. The consequences of such a change can include:
- breaking backwards compatibility;
- code churn (people have to "fix their code" even if it wasn't broken);
- confusion ("what's the difference between def anonymous functions
and lambda anonymous functions?");
- more to learn during the transition (sometimes code uses lambda,
sometimes def, so you need to know both)
- more documentation explaining why the name is only sometimes needed;
- more unit tests etc to ensure the feature works correctly, e.g. to
test for the syntax error when people use def unanonymously when
they should use it anonymously:
map(def func(a, b, c): a+b-c, zip(seq1, seq2, seq3))
Those costs are real and should only be paid when the benefits outweigh
the costs. In this specific case, there's also a very real cost:
- you will *seriously annoy and frustrate* those of us who like lambda
and dislike the look of "def" inside expressions;
- while only *slightly pleasing* those who have already learned lambda
but don't like it. They've already learned the existing word, now they
have to unlearn it.
And the corresponding benefit is tiny:
- The conceptual difficulties with lambda is not the word but the
concept of anonymous functions as first class values; that doesn't
change, so no benefit there.
- One less keyword in the language (after the transition period).
- Two fewer keystrokes.
- but "def" is still jargon that needs to be learned.
(Does it mean defeat, defame, defer, defend, or that thing bears do in
the woods? To a non-English speaker, memorising "def" = "define" is no
less obscure than memorising "lam" = "lambda" would be for English
speakers.)
I don't think this cosmetic change comes even close to the break-even
point of costs versus benefits. Maybe if we were designing Python from
scratch today, there would be a good argument to be made for using def
in both the statement and expression form, but even that's not a sure
thing. Changing it *now* is more costly with less benefit.
To give an example of a problematic keyword where changing it is not
just cosmetic, for many years, consider the "for...else" statement. It
seems to be saying:
run the for loop
*or else* run this block
but that's not what it actually means. But even if we had consensus that
the "else" keyword should be changed (to what? "then" is my suggestion),
the benefit is probably too small to disrupt the Python ecosystem by
actually making that change.
By the way, I'll also point out that the way you have demonstrated the
use of anonymous functions is considered a (mild) abuse of syntax. Your
example:
# reverting back to lambda for the moment
hn = lambda a, b=2, c=3: a ** b / c
ought to be written as:
def hn(a, b=2, c=3): return a ** b / c
which ensures that hn has a nice name for debugging. Lambdas ought to be
limited to in-place uses, as part of a larger expression and not just an
assignment, probably 99% of the time. Hence:
results = map(lambda a, b=2, c=3: a ** b / c, sequence)
widget.register(callback=lambda: spam.eggs())
are reasonable examples of how one might find lambdas in the wild.
Replacing the keyword:
results = map(def a, b=2, c=3: a ** b / c, sequence)
widget.register(callback=def: spam.eggs())
Doesn't look so attractive now, I wager. Using "def" inside an
expression looks strange. And this looks outright disturbing:
def method(self, arg, callback=def arg: arg+1):
pass
--
Steve
More information about the Python-ideas
mailing list