On Sun, 29 Nov 2020 13:39:37 +1300 Greg Ewing email@example.com wrote:
On 29/11/20 4:14 am, Paul Sokolovsky wrote:
On Fri, 27 Nov 2020 13:06:56 +1300 Greg Ewing firstname.lastname@example.org wrote:
There was no mix-up on my side, and neither seems there was on yours. Block-level scoping and const'ness are orthogonal, well composable features.
Someone (maybe not you) suggested "for const i = ..." as a way to address the problem of variable capture in for loops.
I proposed "for const". I didn't propose to use equal sign "=" in the "for" ;-).
The logic behind this seems to be:
- If i is const, rebinding it each time round the loop
is obviously impossible, therefore the loop body must be a new scope in which there is a different i for each iteration.
Please watch your terminology. Because it's exactly right, but implications you make doesn't seem to match the terms. If something is const, it means that you can't *assign* to it. However, the semantics of "for" is that it executes the loop body with "i" *bound* to a new value each time. This is pretty much corresponds to what you said a few messages ago. Except you proposed to implement that literally, and create a new cell for each new value of "i". What I propose is to take advantage that binding of "i" is constant (indeed, formally const'ness applies to binding, not to value bound to), which allows to optimize away the need to create multiple cells.
- Since i is const, we don't need to capture it as a variable,
so as an optimisation we can just capture its value.
But this makes constness and new scopes non-orthogonal, because there's no way to have a new scope for a variable without making it const, and no way to make a variable const without creating a new scope for it.
That's why we don't limit our discussion to just the case of the "for", and consider it in wider language scope, to avoid temptation of choosing a non-generic solution for just "for". But for the situation of "for", we can "strike out" those generic cases which don't apply (well, don't make much sense) to it. So, let's see the full matrix of the "plausible world":
x = 123 for x in seq: print(x) # Possible, doesn't make much sense, but always has been there x = 1 # Prints last item in "seq" print(x)
x = 123 for let x in seq: print(x) # Possible, doesn't make much sense x = 1 # Prints 123 print(x)
x = 123 for const x in seq: print(x) # Error # Prints 123 print(x) x = 1
So, in the plausible domain, there would be "for let", which would introduce a loop variable as mutable (just like classical "for" does). But again, it doesn't make much sense to assign to a loop control var (it will be overwritten on the next loop iter). To emphasize the fact that loop variable belongs to the loop statement (and not to a user), we put our full bet on the "for const" syntax, and don't implement "for let" at all.
But it's only part of the big picture, because we have (even if eventually):
let x = 1 # Possible x = 2
Case 5: const x = 1 # Error x = 2
I also think that "const" is not an *obvious* solution to someone faced with the for-loop problem. They're not trying to reassign the variable anywhere, so there's no reason for constness to come to mind.
It will be much more obvious if there's a general (standalone) "const", that's why I'm saying we can't really consider "for const" without just "const" (even though implementation-wise, one could appear a version or 2 earlier).
And it's "pretty obvious" to someone who considered various choices and saw pieces falling into their places. Also might be pretty obvious for someone who used other languages. It's certainly not a replacement for reading docs, tutorials, and changelogs.
"for const" on its own doesn't make much sense (and neither "for new", i.e. adhoc workaround for the "for" case).
It's not so ad-hoc if "new" can be applied to any assignment.
So assuming conceptual part is clear(er), let's speak of raw words. Among 3 of "new", "const", "let", considering the use as a *standalone* keyword (as in "applied to any assignment") - "new" seems to be the worst choice, sorry. Sorry but even I (a cautious guy) use "new" as a variable name *often*. Yeah, we might address that with over-modern parsers with exponential performance and memory usage, but I hope the point is clear. Extra nag is that "new" is the well-known keyword in other languages, with a different meaning (creating a new object).
I bet I never used "const" as a variable name, but on a bad day, I could. Well, we'll need to deal with that (I vote for non-NP solution!!1). There're not many viable alternatives. I guess we won't take a pun from Rust for example with something like "immut".
Also, if you think "for new" doesn't make sense, you're probably reading it incorrectly. The mental bracketing isn't "(for new) i", it's "for (new i)".
I'm much less tied to words than to concepts and implementation details. So, when I say "for new", I mean "implementation which creates a new cell on each iteration".
This works with "new" and "const", because they're adjectives. But "let" isn't an adjective, so "for let i" doesn't make sense however you parse it.
So, stroke of luck for us that we don't need "for let", only "for const".