Hi

On 12/18/25 10:16, Rowan Tommins [IMSoP] wrote:
The point though is that any answer you give is just a design decision
you've made; and the exact same decision could be made with more
traditional syntax, and apply to the original example.

That is true from a purely technical perspective, since syntax is independent from semantics. But the choice of syntax influences users' expectations with regard to semantics and as I've outlined, we believe that the semantics we've chosen fits PHP best and that the syntax we've chosen hints at the semantics best.

To me the syntax of the `let()` construct very strongly suggests (3)


I don't really see why. As I said above, the comma-separated list made
me think of "simultaneous" action, which I think would imply (1),
because accessing a variable "while it's being declared" would make no
sense.

Part of it probably is probably a subconscious feeling, but I'll try with an explanation that you may or may not be able to agree with.

Existing constructs in PHP that take a list of multiple “items” behave equivalent to consecutive single-item entries. Or in less abstract terms:

    const FOO = 1, BAR = 2;

is equivalent to:

    const FOO = 1;
    const BAR = 2;

So to me it is only natural to extend that logic to the `let()` construct, which only leaves the let($a) let ($b) desugaring which then implies (3).

In fact, the following works:

    const FOO = 1, BAR = FOO + 1;
    var_dump(FOO, BAR);

and defines `BAR = 2` and

    const FOO = BAR + 1, BAR = 1;

throws, because `BAR` is undefined when defining `FOO`. This is exactly matching the proposed semantics of `let()`.

Option 3 is not necessarily a "wrong" choice, but it's a choice you have
made, and you could equally use more traditional syntax and make that
same choice.

Yes, but the “more traditional syntax” would also leave the possibility of (1) or (2) - unless restricted to the start of the block as in C90. However it would compose less well with the existing control structures, e.g. by requiring the dedicated syntax for declarations that should live for a single `if()` construct.

The only thing that using commas automatically does is forbids jump
targets (goto labels or switch cases) in between the declarations.

It also forbids nested blocks and any other “arbitrarily complex code” in-between declarations. Yes, I understand that folks can use arbitrary expressions on the right side of the declaration (including assignments), but that is more unlikely compared to a more “free-form” syntax that allows arbitrary statements, including arbitrary control flow.

I also believe that the explicit separation of declaration and usage provides for a nice visual barrier of "before declaration, definitely old variable", "after declaration, definitely new variable" and "declaration phase, a small chance of ambiguity when declaring a variable that is used in the declaration of an earlier one".

Best regards
Tim Düsterhus

Reply via email to