Hi
Am 2025-11-11 23:43, schrieb Rowan Tommins [IMSoP]:
That's fair. I'll look into adding more explicit comparisons to the
RFC together with Seifeddine. My short answer here would be that
JavaScript already had explicit scoping by means of `var` and thus
folks are already used to needing to declare variables. Moving to
`let` is just a smaller incremental change. This is different from PHP
where all variables exist implicitly, which also means that semantics
from other languages need to be adapted.
Technically, JavaScript variables don't have to be declared either; the
difference is that they are global by default, and since function-scope
is generally more useful, people are indeed very familiar with "var".
You are correct, my remark was too simplified. To add to that: If you
use `"use strict";` then the implicit fallback to global variables will
not happen and an error will be emitted instead:
"use strict";
function foo() {
a = 1;
}
foo();
results in: "ReferenceError: a is not defined".
PHP does have optional keywords that declare a variable with specific
scope, just much less frequently used: "global" and "static". Regarding
the discussion on shadowing vs hoisting:
- Both "global" and "static" can shadow local variables, and indeed
each other: https://3v4l.org/vPr2A
- Since the shadowing lasts until the end of the function, a shadowed
local variable is never re-instated, and will be de-allocated if it was
the only reference: https://3v4l.org/VBVkX
- Somewhat unusually, they do this as run-time statements, so you can
*conditionally* shadow variables: https://3v4l.org/fK9VJ
Whether these are *good* semantics to copy for a block-scoped variable,
I'm not sure; but they are existing PHP semantics for a very similar
situation.
Thank you. I just learned that `global` didn't need to be at the start
of a function - which might perhaps be an indication that folks will
already put the global at the top in practice, possibly because it is
confusing otherwise. As a trivia knowledge I also learned that `global`
supports variable variables: https://3v4l.org/oQLjP
With regard to the RFC, I've adjusted the implementation (and RFC text)
to make the following changes:
- Neither `global`, nor `static` may be used from within the `use()`
block.
- `static` variables defined *before* the `use()` may not be used.
`static` variables defined *after* are okay, since there is no
ambiguity.
- `global` variables may be used. This is consistent with `unset()`
allowing to break the relationship with the global:
https://3v4l.org/j2tRa. From what I understand, `global $foo;` is
equivalent to `$foo = &$GLOBALS['foo'];`.
I'm not aware of any language that requires a specific kind of block
in order to introduce a new scope, but that doesn't mean it's a bad
idea. The approaches I am aware of are:
The closest comparison to “specific kind of block” might perhaps be
older versions of C which require all variables to be declared - and
for them to be declared at the top of the scope without any logic
running in-between.
The big difference is the need for an extra level of indent (or, at
least, an extra pair of braces, which most people will probably assume
needs an extra level of indent). More often than not, there is an
existing block you want to scope to - a particular loop, or a
conditional branch, etc.
Please note that the `use()` construct does not necessarily require
braces. Thus both of the following would already work:
use ($foo) if ($bar) {
//
}
and
if ($bar) use ($foo) {
//
}
I do see the advantage of forcing them to the start, though. Languages
in the Pascal family might be another comparison to explore - variables
are all declared in a separate block at the top of a function.
Off-hand, I'm not sure if any allow an arbitrary nested block just to
introduce additional variables.
We'll look into more research in that direction.
Best regards
Tim Düsterhus
PS: I'll be on vacation Thursday - Sunday, so please be prepared for
some delay in replying :-)