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 :-)

Reply via email to