[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