Paul Sokolovsky writes:

 > Also to clarify, [cowboy attitude] referred to difference in
 > approaches in response to particular issue(s) raised. One thing is
 > to say "it's hard to implement it better with the limited VM
 > infrastructure and resources we have" (that of course leads to
 > further questions/discussion), it's different thing to say to the
 > same matter "issue exists, but it's not really an issue".

Of course those are *different*.  Where I differ with you is on
whether "I understand the case are describing and that you want to do
something about it, but we don't consider that a problem" is "cowboy

My experience is that the development community will care when it
perceives that a change serves the greater community (eg, f-strings
and data classes, which are universally loved), or when a sufficiently
large coalition of committers can be convinced.  That's what you need
to do, and accusing the core developers of cowboy attitude is not a
good start IMO.

 > Maybe one of these years would be good time, after so many
 > usability changes, to also tighten up theoretical side with
 > block-level scoping.

Maybe it is.  I certainly hope not, because I like Python as it is,
where I rarely have to deal with declarations separate from
instantiation, and code is highly dynamic without a compiler
complaining, perhaps even going on strike, any time I want to do
something whose semantics I know to be sound even though the compiler
can't prove that from the syntax.

Yes, I know you claim that your proposed syntax won't be in my face,
and quite possibly you're right with respect to the obstreperous
compiler.  But I also know that you make claims that are provably
false, such as not making me use the syntax.  True, short of XKCD 538
you can't make me write it, but if it exists somebody will make me
read it.

 > The simplest answer is that they don't (interact with existing
 > overdynamic features).

You say "overdynamic", I say "works for me".

 > They are new enough, opt-in concepts, and so can start from blank
 > page.

You're BS-ing here -- you back off in the next sentence (quoted
below).  And from the community's point of view, no syntax is truly
opt-in because we often work with Other People's Code.  We need to
read it, and often in open source we are modifying code whose style is
"owned" by someone else -- if I were to work on code you maintain, I'm
pretty sure you wouldn't hesitate to query "shouldn't this variable be
block local" or even refuse to accept code that didn't have the block
locals you think it should have.

A lot of effort and persuasion (and more or less silent acceptance of
the slings and arrows from outraged dynamicists) went into the
introduction of type hints.  I think this will require more of the
same (although maybe not: type hints are intentionally pervasive for
those who use them, these declarations will presumably be occasional).

 > Alternatively, if debuggers, etc. are tied to locals() (vs more
 > low-level code object introspection), could add
 > implementation-defined support for them in locals() for simple
 > implementations like CPython (block-local names will be mangled).

Sure, but we don't have an implementation of that support yet, do we?
And adding the syntax will impose burdens on other implementations
that claim to support the full language, as well as quite possibly
inducing implementation differences here, unless you specify the
debugger support etc.  My point is that these are the kinds of
complications that frequently delay acceptance of features for a
release or two.

 > > I suspect that when I'm reading other people's code I'd almost
 > > certainly read a let/const var = init_val as suite- local in such
 > > contexts, while in my own code I'd probably want to use it as
 > > statement-local a lot.
 > It's unclear how block-level scoping can be useful for single-statement
 > scopes (beyond special cases like comprehensions), because well, that
 > single statement will be assignment to such a variable (but nothing
 > will read it). I even suspect we might imagine different things when
 > talk about this, perhaps examples would help.

By "if statement" I mean

    if foo():
    elif bar():

That is a single conditional *statement* with three suites that each
might constitute an individual block or together constitute a single
block (encompassing the if and elif condition expressions as well).  I
believe that's how the Python Language Reference uses "statement".

 > 1. We have adhoc block-scope-alikes already.

Yes, there's the problematic deletion of exception-capture variables,
but I don't think the plural is justified.  Comprehensions are
*expressions*, not suites.  Python is a *high level* language: the
fact that

    [x for x in y]

effectively expands to

    list((x for x in y)) ,

implicitly defining a generator function and iterating that, doesn't
bother me at all.  It's an expression, and there's no reason for its
internals to be available to the scope it occurs in, any more than v
or x in

    def foo(y):
        v = []
        for x in y:
        return v

should be available in the scope where foo is called.  AIUI, the
decision to expose x in the comprehension was so that the explanation
"the comprehension above is equivalent to the suite in foo (except
that no name is bound to the object denoted by 'v')" would be exact,
including the leakage of x (but not v) into the containing scope.
That's a pretty arbitrary reason, but ease of explanation is valued in
Python, as is simplicity of implementation.  I think you have to admit
that given that generator expressions exist, "list((x for x in y))" is
about as simple a semantics and implementation as you could ask for.

 > 2. We have on the plate cases where block scope may help.

I'll take your word for that.  I don't know that I've ever run into
any, and I do know that I've never thought "Damn, I wish I could use
block locals here" or "I wish the author of this code had used block
locals here" in Python (though I occasionally use block scope in C).
Of course *I* don't matter, but the relative balance between folks
with your experience and folks with mine does.

 > 3. So, convert to "real" block scoping there.

Whoa!  First you have to convince the core devs that block scope
really does help, and that it's the best way to improve the language's
ability to express solutions to these issues.  I'll trust you that it
*does* address the issues.  But whether it's best is entirely unclear
to me.  Perhaps there are are semantic tweaks like changing the
intuitive explanation of comprehension from "a list comprehension is
equivalent to an obvious inlined for statement" to "a list
comprehension is list applied to the obvious genexp".

You don't like that particular semantic tweak because its
implementation involves creating an "unnecessary" function, I know,
but I do, because it unifies two similar expressions (actually, at
least four), making one a trivial extension of the other.

 > 4. Don't stop there, and *let* people use explicit block-level vars if
 > they need.
 > It's "let", don't "make" people use it.

Please, that's just factually wrong.  If you write it, I have to read
it if I want to understand your program.  If you don't intend to write
code for me to read, why do we need to have the same language?  Fork,
and use your improved Python-like language for your private code.
You'll still be able to read my code, much of which is intended for
public use and visibility.

 > If you *really* need block-level local, perhaps just being able to
 > use it (without rehashing half of the language) is good enough, for
 > starters.

You continue to overstate your case.  Nobody *really* *needs* block
locals.  Like type hints, they may be a great convenience for
detecting certain kinds of logic errors, but they don't allow you to
do any computation in the language you couldn't already do in the same
number of lines, even the same number of tokens.

 > > But requiring a "block" statement to create a slope in common
 > > cases like a one-armed if or for is equally inelegant (and surely
 > > more common).

But not necessarily equally costly if misunderstood, and the "always
need a block statement to create a block" approach is easier to
understand and explain correctly.  And I disagree with you that mere
verbosity is "inelegant".  Concise syntax is a virtue, but so is
consistent syntax.  IMO, elegance lies in achieving both in the same
construct.  I'm not sure if elegance is possible here, consistent with
existing Python syntax.

 > In "case a, b if ...:", if the case *doesn't* match, do you expect a
 > and b be assigned?

Mu.  I can both not expect them to be assigned, and not expect them to
not be assigned, at the same time.  I can learn either.

 > [When] you intuitively expect special scoping rules for at least
 > the "case" line itself, [...] the block scope is the best well-
 > proven formalism in the proglanguage theory/practice which matches
 > that requirement.

Sure, but Python is not a Lisp.  Adding arbitrary user-defined block
scopes is not just a matter of one more pair of parentheses.  So
"best" has to be constrained by "Pythonicity", and I don't think your
computer-scientific proofs can handle Pythonicity yet.
Python-Dev mailing list --
To unsubscribe send an email to
Message archived at
Code of Conduct:

Reply via email to