[Python-ideas] An alternative to PEP 572's Statement-Local Name Bindings

Greg Ewing greg.ewing at canterbury.ac.nz
Fri Mar 2 20:36:39 EST 2018

PEP 572 as it stands seems to have many problems:

* Asymmetry between the first and subsequent
   uses of the bound value
* Embedded as-clauses are subtle and hard to spot
* Ever more convoluted semantics are being invented
   to address percieved pitfalls

Alternative proposal

Getting back to the original motivating use case of
intermediate values in comprehensions, to my mind there
is really only one clear and obvious way to write such

    [(f(y), g(y)) for x in things where y = h(x)]

Possible objections to this:

* Requires a new keyword, which may break existing code.

- Yes, but "where" is an unlikely choice of name, being
neither a noun, verb or adjective, so it probably wouldn't
break very *much* code. In return, we get something that
resonates with language mathematicians have been using
for centuries, and a word that can be usefully googled.

* Out-of-order evaluation

- Comprehensions and if-expressions already have that.

Extension to other use cases

There are some other situations in which it could be
useful to have a similar construct.

1. Name bindings local to an expression:

    roots = ([(-b-r)/(2*a), (-b+r)/(2*a)] where r = sqrt(b*b-4*a*c))

2. Names bound as part of an expression and also available
in a following suite:

    if m where m = pattern.match(text):

There's a problem, though -- if "where" in an expression
creates bindings local to that expression, they're not
going to be visible in the rest of a comprehension or
compound statement.

So I'm thinking that there would actually be three distinct
usages of "where":

A. As a clause in a comprehension, where it creates bindings
local to the comprehension and is treated on the same footing
syntactically as "for" and "if" clauses.

B. In an expression, surrounded by parentheses for
disambiguation. Bindings are visible only within the

C. Following the expression of an "if" or "while" statement.
Bindings are visible within the preceding expression and the
following suite.

Note that case B avoids the issue of whether expression-local
bindings affect the LHS of an assignment, because in

    a[x] = (x * 2 where x = 17)

the "x" bound by the where-clause is clearly restricted to
the part in parentheses. This would be a syntax error:

    a[x] = x * 2 where x = 17    # illegal


More information about the Python-ideas mailing list