On Mon, 30 Nov 2020 01:54:53 +0900 "Stephen J. Turnbull" email@example.com wrote:
Paul Sokolovsky writes:
Well, I'd call that "cowboy attitude in programming language design" ;-).
That was uncalled for, especially since you're selling an idea without an implementation yourself.
Ok, I posted my "cowboy" implementation (i.e. a prototype) of block-level scoping for the "for" now: https://firstname.lastname@example.org/thread/MMEIYOK... , to make that even.
Also to clarify, that 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".
We'd certainly make it blend well with the rest of Python.
But how long will that take? People have wanted f-strings since forever (1.5 is as far back as I go, PEP 215 was July 2000). We got them in 3.6 (December 2016), the delay basically due to "blending" issues. And that was for a quite self-contained feature.
If anything, "Unlikely Adventures of Python in 3.x Era", is what motivates me to continue this discussion. Alternatively, consider what a conceptual jump happened in 2.1, when function-level nested scoping was introduced. Maybe one of these years would be good time, after so many usability changes, to also tighten up theoretical side with block-level scoping.
This one strikes me as likely to be messy. How does we get consistency if we don't change for? How do block locals interact with global, nonlocal, and locals()? Do we need a block_locals()?
The simplest answer is that they don't (interact with existing overdynamic features). They are new enough, opt-in concepts, and so can start from blank page. 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).
Currently all suites in a multiarmed statement (if, for, while, try) are in the same scope.
Well, I definitely advocate a solution where a Python suite == block scope, which for example means that "true" vs "false" suites of the "if" are different scopes.
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.
Of course that latter is easy to handle by creating a new suite with something like "if 1" (as you suggest elsewhere), but creating unconditional 1-statement suites just to declare block-locals seems excessively inelegant. :-/
This is somewhat backwards to the motivation I try to promote. My motivation is:
1. We have adhoc block-scope-alikes already. 2. We have on the plate cases where block scope may help. 3. So, convert to "real" block scoping there. 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. 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.
That said, if you want my bet for the best block-level introduction way, not requiring new keywords, it's:
with: # yeah, empty with! let x = 1
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).
Arm on an "if" is already a block scope, per above.
The problem is that intuitively (just like with "for"), "case a, b if a != b:" opens a new namespace for "a" and "b".
I don't find a new namespace in either of those contexts intuitive at all. Nor do I find it unintuitive at all. A language will define rules for scoping, I'll learn them.
In "case a, b if ...:", if the case *doesn't* match, do you expect a and b be assigned? If you don't, then you intuitively expect special scoping rules for at least the "case" line itself, and the block scope is the best well-proven formalism in the proglanguage theory/practice which matches that requirement.