On 2018-03-02 03:43, Chris Angelico wrote:
After dozens of posts and a wide variety of useful opinions and
concerns being raised, here is the newest version of PEP 572 for your
debating pleasure.

After following the discussion here, I think I've come to the conclusion that something like "EXPR with NAME as VALUE" is better, and that's because the "out-of-order" execution there is actually a benefit.

The example that gave me the most pause in this thread was Paul Moore's involving the quadratic formula (slightly emended here :-):

x = [(-b + sqrt((b**2 - 4*a*c as D))/(2*a), (-b + sqrt(D)/(2*a)]

To me this is a classic example of the kind of thing I would want to do with a statement-local binding, so whatever syntax is chosen won't be useful to me if it doesn't nicely work in situations like this.

But I don't find the above example nice, for more or less the reason Paul cited: the need to assign the expression "inline" (at the point where it's first defined) creates an asymmetry that masks the fact that it's the same expression being re-used elsewhere --- and it's exactly that re-use that I would want to HIGHLIGHT with a statement-local binding.

        The alternative with the name binding at the end is much better:

x = [(-b + sqrt(D))/(2*a), (-b - sqrt(D))/(2*a) with b**2 - 4*a*c as D]

To my mind, it's a real desideratum for a statement-local binding that it should pull the bound expression OUT of the enclosing context. The overall statement gains in readability only if the reader can easily see a shared element across multiple parts. If I can't tell at a glance that the two roots both involve the same value D, there's little point in having a statement-local binding for it. (It still may gain in computational cost, since the expression won't have to be evaluated multiple times, but I see that as a much less important benefit than readability.)

Also note that the version above comes perilously close to the existing solution with a regular local variable:

D = b**2 - 4*a*c
x = [(-b + sqrt(D))/(2*a), (-b - sqrt(D))/(2*a)]

The only difference is that now D is "leaked" to following code. Nick Coghlan has argued that there's no point in an inline-assignment construct if it's not somehow local, since a big part of its purpose is to simplify reasoning by avoiding any stomping on "real" local variables.

But if that's the case, maybe what we want is actually another thing that's been discussed many times on this list, namely something like a with-block that can define "super-local" variables that disappear at the end of the block:

with b**2 - 4*a*c as D:
    x = [(-b + sqrt(D))/(2*a), (-b - sqrt(D))/(2*a)]

This the same as my earlier version with "with", except the with clause comes at the beginning.

There's no need to go into extreme detail here on these proposals as they're not really what's proposed by this PEP. But my point is that, from my perspective, they have something crucial that the current proposal lacks: they explicitly separate the *definition* of the shared expression from its *use* within the statement. Having to do the name-binding inline at the place where the re-used expression happens to occur makes the overall construct LESS readable for me, not more, so I'm -1 on the current proposal.

Brendan Barnwell
"Do not follow where the path may lead. Go, instead, where there is no path, and leave a trail."
   --author unknown
Python-ideas mailing list
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to