On 6 May 2026 21:09:45 BST, Bob Weinand <[email protected]> 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]

Reply via email to