Re: [RFC] Scope functions
| From: | Rowan Tommins [IMSoP] | Date: | Thu, 07 May 2026 10:52:42 +0000 |
| Subject: | Re: [RFC] Scope functions | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-130790@lists.php.net to get a copy of this message | ||
On 6 May 2026 21:09:45 BST, Bob Weinand <bobwei9@hotmail.com> wrote:
>Volker and I drafted a RFC:
>
>https://wiki.php.net/rfc/scope-functions
Hi Bob,
An I right in thinking that this is essentially equivalent to "automatic capture by
closure", with an extra restriction on the lifetime of the resulting closure? It would be good
to spell out in the RFC how this compares to other approaches, and other languages.
In particular, JavaScript's capture semantics are somewhat notorious as a source of confusion.
A common example is creating closures in a loop which all use the same variable; as far as I can
see, the proposed semantics would allow this as long as they were executed before the parent scope
ends:
```
function parent_scope() {
$values = range(1,10);
$scoped_functions = [];
foreach( $values as $v ) {
$scoped_functions[] = fn($v) {
echo "Chosen item is {$v}";
};
}
run_random_callable($scoped_functions);
}
/**
* @param callable[] $callables
*/
function run_random_callable($callables) {
$pick = array_rand($callables);
$callables[$pick]();
}
// Will always output 'Chosen item is 10'!
// The list of "scoped functions" will all actually refer to the same $v, updated in the
loop
parent_scope();
```
I don't know if there's some way to make the lifetime even more restricted, so that the
use cases of "immediate execution" are allowed, but this kind of code is not.
For something like "run this in a transaction", the closure is really acting like a poor
man's "continuation": it creates two new stack frames (transaction wrapper, callback)
when what you really want is to *interleave* the boilerplate and the case-specific code.
In that sense, hygienic macros are probably the "ideal" solution - everything is expanded
inline into a single scope, and there's no Closure object which can be misused.
Context Managers could in fact be implemented as such a macro, and as I understand it, the
implementation is basically doing that internally by manipulating ASTs.
I wonder if there's any "minimal" macro system which would allow this kind of inline
boilerplate expansion, without needing to design an entire meta-language?
Regards,
Rowan Tommins
[IMSoP]