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