On 2 March 2018 at 19:05, Paul Moore <p.f.mo...@gmail.com> wrote:
> The problem with statement local variables is that the extent over
> which the name is in scope is not as clear to the human reader (the
> rules the *compiler* follows may be precise, but they aren't obvious
> to the human reader - that's the root of the debate I'm having with
> Chris over "what the reference implementation does isn't a sufficient
> spec"). In particular, assignment statements are non-obvious, as shown
> by the examples that triggered your suggestion of a "." prefix.
Those examples didn't trigger the suggestion: the suggestion was borne from
the fact that I don't think it should be possible to close over statement
If you can't close over statement locals, then it isn't acceptable to allow
x = 12
if (True as x):
print(x, f()) # "True True"? Or "True 12"?
print(x, f()) # "12 12", but it's not obvious why it isn't "True True"
By contrast, if the two kinds of local namespace are visibly different,
then the nested scope *can't* give the appearance of referencing the
x = 12
if (True as .x):
print(.x, x, f()) # Clearly "True, 12, 12", since x never gets
print(x, f()) # Clearly "12, 12", since x never gets rebound
> > Adding statement local variables into that mix *without* some form of
> > syntactic marker would mean taking an already complicated system, and
> > it even harder to reason about correctly (especially if statement locals
> > interact with nested scopes differently from the way other locals in the
> > same scope do).
> Well, an alternative to a syntactic marker would be an
> easy-to-determine extent. That's where proposals like PEP 3150 (the
> "given" clause) work better, because they provide a clearer indication
> of the extent of the new scope. IMO, lack of a well-defined extent is
> a flaw of this proposal, and syntactic markers are essentially a
> (ugly) workaround for that flaw.
PEP 3150 ended up needing syntactic markers as well, to handle the forward
references to names set in the `given` clause while staying within the
LL(1) parsing design constraint imposed on Python's grammar.
Currently it proposes `?.name` as that marker, with `?` referring to the
entire given namespace, but it could equally well use `.name` instead (and
if you wanted a reference to a namespace instead, you'd need to define one
inside the given clause).
One of the key *problems* with PEP 3150 though is that it doesn't compose
nicely with other compound statements, whereas PEP 572 does (by treating
each statement as its own extent - PEP 3150 then just provides a way to add
a suite to statements that don't already have one of their own).
> > Thus the intent behind the ".NAME" suggestion is to ask whether or not
> > possible to allow for name bindings that are strictly local to a
> > unit (i.e. without allowing dynamic runtime access to outer scopes or
> > contained scopes), *without* incurring the cost of making ordinary NAME
> > references even more complicated to understand.
> ... or the cost of imposing a more user-visible indication of the
> extent of the scope into the proposal.
Right, but that extra notation *does* convey useful information to a reader
that better enables local reasoning about a piece of code. Currently, if
you're looking at an unfamiliar function and see a name you don't
recognise, then you need to search the whole module for that name to see
whether or not it's defined anywhere. Even if it's missing, you may still
need to check for dynamic injection of module level names via globals().
Seeing ".name" would be different (both for the compiler and for the human
reader): if such a reference can't be resolved explicitly within the scope
of the current statement, then *it's a bug* (and the compiler would be able
to flag it as such at compile time).
Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia
Python-ideas mailing list
Code of Conduct: http://python.org/psf/codeofconduct/