Hi
Am 2025-11-10 11:04, schrieb Rowan Tommins [IMSoP]:
On 09/11/2025 16:52, Tim Düsterhus wrote:
We don't think so. Our goal with this proposal is - as the title of
the RFC suggests - making block scoping / limiting lifetimes of
variables more convenient to use. The goal is to make it easier for
developers and static analysis tools to reason about the code, for
example because variables are less likely to implicitly change their
type.
Perhaps part of the problem is the comparisons the RFC calls on. It
mentions features from three existing languages, none of which is about
block scoping; and doesn't mention the ways other languages *do*
indicate block scoping.
I can see how this is a possible source of confusion. The motivation of
this RFC was to improve handling of lifetimes (both regular variables
and resource objects) and for that we looked into the listed references,
since we were familiar with them to varying degrees. Afterwards we
looked at how these languages differ from PHP and adapted the concepts
into something that we believe fits the existing semantics of PHP best.
From my experience, taking another programming language's feature as-is
and putting it into PHP is almost never the right choice.
I also wouldn't say that the RFC is drawing an explicit comparison to
the other languages. It just lists them as references / source of ideas,
but I can see how we could spell out more explicitly why we made the
changes compared to those other languages or that those are just a rough
inspiration.
Syntax-wise the solution ended up similarly to those three languages,
but when we were looking at the semantics, PHP's destructor semantics
are quite different than those of the other languages. That's why the
semantics differ from the three references and became “block scoping it
is” for RFC we are proposing, since that implicitly handles resource
objects.
If what you're interested in is a general-purpose block scope, none of
these are relevant examples. The most relevant that comes to my mind is
JavaScript's "let", which is an opt-in block scope added to an exsting
dynamic language. A comparison of that approach to what you propose
here would be interesting.
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.
Yes, this is a problem that any language with block-scoping has to
tackle. Since there are many languages which have that feature, I'm
sure plenty has been written on the pros and cons of different
approaches.
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.
- Shadowing: At the point of declaration, any other variable with the
same name becomes inaccessible, but not over-written. Result: 1, 1, 2,
1
- Forbidden shadowing: At the point of declaration, if there is another
variable of the same name in scope, an error occurs. Result: 1, 1,
Error (let statement must not shadow $a from outer scope)
- Hoisting: The variable declaration can occur anywhere in the scope,
and affects the whole scope even lines above it. Used by JavaScript's
"var" keyword, and very confusing. Result: 1, 2, 2, 1
- Forbidden hoisting: The variable declaration can occur anywhere in
the scope, but lines above that point are forbidden from accessing it.
Used by JavaScript's "let" keyword, with the dramatic name "Temporal
Dead Zone". Result: 1, Error (must not access block variable $a before
declaration)
As mentioned before, many other languages already require explicit
variable declarations for everything. For those it's fairly clear that
variables do not exist before their declaration. With PHP variables
implicitly coming to life on the first usage, we don't believe that any
of those existing semantics are fitting a PHP developer's intuition and
therefore opted to require all “block scoped” variables to be declared
right at the start of the block to avoid the ambiguity of when the block
scoping actually starts for a given variable. The semantics of the block
are then equivalent to shadowing after we made the changes to restore
the original value afterwards.
Best regards
Tim Düsterhus