[Python-Dev] Informal educator feedback on PEP 572 (was Re: 2018 Python Language Summit coverage, last part) (original) (raw)
Paul Moore p.f.moore at gmail.com
Mon Jun 25 08:25:09 EDT 2018
- Previous message (by thread): [Python-Dev] Informal educator feedback on PEP 572 (was Re: 2018 Python Language Summit coverage, last part)
- Next message (by thread): [Python-Dev] Informal educator feedback on PEP 572 (was Re: 2018 Python Language Summit coverage, last part)
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On 25 June 2018 at 12:44, Nick Coghlan <ncoghlan at gmail.com> wrote:
Unfortunately, I think the key rationale for (b) is that if you don't do something along those lines, then there's a different strange scoping discrepancy that arises between the non-comprehension forms of container displays and the comprehension forms:
I've been mostly ignoring this proposal for a while now, so I'm going to respond here in the context of someone with a bit of an idea of the underlying complexities, but otherwise coming at it as a new proposal.
(NAME := EXPR,) # Binds a local tuple(NAME := EXPR for _ in range(1)) # Doesn't bind a local [NAME := EXPR] # Binds a local [NAME := EXPR for _ in range(1)] # Doesn't bind a local list(NAME := EXPR for _ in range(1)) # Doesn't bind a local {NAME := EXPR} # Binds a local {NAME := EXPR for _ in range(1)} # Doesn't bind a local set(NAME := EXPR for _ in range(1)) # Doesn't bind a local {NAME := EXPR : EXPR2} # Binds a local {NAME := EXPR : EXPR2 for _ in range(1)} # Doesn't bind a local set((NAME := EXPR, EXPR2) for _ in range(1)) # Doesn't bind a local
None of those "discrepancies" bother me in the slightest, when taken in isolation as you present them here. I suspect you could lead me through a chain of logic that left me understanding why you describe them as discrepancies, but without that explanation, I'm fine with all of them.
I'd also say that they seem contrived (not just in the use of artificial names, but also in the sense that I'm not sure why I'd want to use this pattern) so I'd happily say "well, don't do that then" if things started behaving non-intuitively.
Those scoping inconsistencies aren't new, but provoking them currently involves either class scopes, or messing about with locals().
And to reinforce my point above, I already consider putting significant code in class scopes, or using locals() to be techniques that should only be used sparingly and with a clear understanding of the subtleties. I'm sure you could say "but the examples above would be much more common" in response to which I'd like to see real use cases that behave non-intuitively in the way you're concerned about.
The one virtue that choosing this particular set of discrepancies has is that the explanation for why they happen is the same as the explanation for how the iteration variable gets hidden from the containing scope: because "(EXPR for ....)" et al create an implicitly nested scope, and that nested scope behaves the same way as an explicitly nested scope as far as name binding and name resolution is concerned.
But that's precisely why I find the behaviour intuitive - the nested scope is the reason things behave this way, not some sort of easily-overlooked way the "problem" can be explained away.
Parent local scoping tries to mitigate the surface inconsistency by changing how write semantics are defined for implicitly nested scopes, but that comes at the cost of making those semantics inconsistent with explicitly nested scopes and with the read semantics of implicitly nested scopes.
The early iterations of PEP 572 tried to duck this whole realm of potential semantic inconsistencies by introducing sublocal scoping instead, such that the scoping for assignment expression targets would be unusual, but they'd be consistently unusual regardless of where they appeared, and their quirks would clearly be the result of how assignment expressions were defined, rather than only showing up in how they interacted with other scoping design decisions made years ago.
Those last two paragraphs made my head explode, as far as I can see by virtue of the fact that they try to over-analyze the fairly simple intuition I have that "there's a nested scope involved".
Disclaimer: I may well have got a lot of subtleties wrong here, and it's quite likely that my impressions don't stand up to the harsh reality of how the implementation works. But my comments are on the basis of my intuition, whether that's right or wrong. And if the reality violates my intuition, it's other constructs that I find non-intuitive, not this one. (I'm perfectly happy to concede that it's not possible to avoid any non-intuitive behaviour - all I'm trying to say is that my intuition doesn't balk at this one, unlike yours).
Paul
- Previous message (by thread): [Python-Dev] Informal educator feedback on PEP 572 (was Re: 2018 Python Language Summit coverage, last part)
- Next message (by thread): [Python-Dev] Informal educator feedback on PEP 572 (was Re: 2018 Python Language Summit coverage, last part)
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]