seeking deeper (language theory) reason behind Python design choice

Steven D'Aprano steve+comp.lang.python at pearwood.info
Mon May 7 20:45:29 EDT 2018


On Mon, 07 May 2018 22:27:22 +0200, all-lists wrote:

> Hi,
> 
> I was wondering (and have asked on StackOverflow [1] in a more elaborate
> way) whether there is a deeper reason to not allow assignments in lambda
> expressions.

Currently, the real reason is that lambda expressions are limited to a 
single expression as the body of the function, and binding operations in 
Python are statements. It is as simple as that: you can't have

    y = x + 1

inside a lambda for the same reason you can't have

    import spam
    while condition:
        try:
            this()
        except Exception:
            pass

Because lambda takes a single expression.

And the reason for *that* limitation is that after 20+ years of looking, 
nobody has come up with a satisfactory syntax for a multiple statement 
block expression which:

- is not ambiguous

- can be parsed by an LL(1) parser

- and meets Guido's approval.


Nobody has quite ruled out a block expression, in fact it is one of the 
acknowledged useful features which Ruby has that Python doesn't. So its 
not like we don't want it. Its just hard to do without ambiguity or a 
more complex parser.


> 
> I'm not criticising, I'm asking in order to know ;-)
> 
> The surface-reason is the distinction between assignments and
> statements, but why it was designed this way (with respect to lambda,
> not in general)?
> 
> So far, no satisfying answer has come up, except for maybe to avoid a
> programmer accidentally typing `=` instead of `==`, which I find a bit
> unsatisfying as the only reason.

No, that's the reason why = is a statement not an expression. That's not 
why statements aren't allowed in lambdas. If we had blocks, this would be 
perfectly acceptable:

lambda arg: %%%START BLOCK
    spam = arg + 1
    ...
    %%%END BLOCK

since = in a statement on its own is not dangerous. People *almost never* 
intend to write == for the side-effects only:

    # don't care whether they are actually equal or not
    # just want to call the __eq__ method for its side-effects
    spam == arg + 1

Since that never happens in real life, there's no risk of accidentally 
writing "spam = arg + 1" when you wanted "spam == arg + 1".




-- 
Steve




More information about the Python-list mailing list