On samedi 11 juin 2022 23:14:28 CEST Rowan Tommins wrote: > My main concern is summed up accidentally by your choice of subject line > for this thread: is the proposal to add *short closure syntax* or is it > to add *auto-capturing closures*?
The proposal is to extend the Arrow Functions syntax so that it allows multiple statements. I wanted to give a name to the RFC, so that we could refer to the feature by that name instead of the longer "auto-capture multi- statement closures". But the auto-capture behavior is an important aspect we want to inherit from Arrow Functions. > As such, I think we need additional features to opt > back out of capturing, and explicitly mark function- or block-scoped > variables. Currently the `use()` syntax co-exists with auto-capture, but we could change it so that an explicit `use()` list disables auto-capture instead: ```php fn () use ($a) { } // Would capture $a and disable auto-capture fn () use () { } // Would capture nothing and disable auto-capture ``` > On the other hand, "auto-capturing" could be seen as a feature in its > own right; something that users will opt into when it makes sense, while > continuing to use explicit capture in others. If that is the aim, the > proposed syntax is decidedly sub-optimal: to a new user, there is no > obvious reason why "fn" and "function" should imply different semantics, > or which one is which. A dedicated syntax such as use(*) or use(...) > would be much clearer. We could even separately propose that "fn" and > "function" be interchangeable everywhere, allowing combinations such as > "fn() use(...) { return $x; }" and "function() => $x;" Unfortunately, Arrow Functions already auto-capture today, so requiring a `use(*)` to enable auto-capture would be a breaking change. > I don't find the comparison to a foreach loop very convincing. Loops are > still only accessing variables while the function is running, not saving > them to be used at some indeterminate later time. Do you have an example where this would be a problem? > This is also where comparison to other languages falls down: most > languages which capture implicitly for closures also merge scopes > implicitly at other times - e.g. global variables in functions; instance > properties in methods; or nested block scopes. Generally they also have > a way to opt out of those, and mark a variable as local to a function or > block; PHP does not, because it has always required an opt *in*. These languages capture/inherit in a read-write fashion. Being able to scope a variable (opt out of capture) is absolutely necessary otherwise there is only one scope. In these languages it is easy to accidentally override/bind a variable from the parent scope by forgetting a variable declaration. Auto-capture in PHP is by-value. This makes this impossible. It also makes explicit declarations non-necessary and much less useful. > Which leads me back to my constructive suggestion: let's introduce a > block scoping syntax (e.g. "let $foo;") as a useful feature in its own > right, before we introduce short closures. I like this, especially if it also allows to specify a type. However, I don't think it's needed before this RFC. > As proposed, users will need to have some idea of what "live variable > analysis" means, or add dummy assignments, if they want to be sure a > variable is actually local. With a block scoping keyword, they can mark > local variables explicitly, as they would in other languages. Live-variable analysis is mentioned in as part of implementation details. It should not be necessary to understand these details to understand the behavior of auto-capture. I've updated the "Auto-capture semantics" section of the RFC. Regards, -- Arnaud Le Blanc -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php