On Wed, Mar 24, 2021 at 5:20 PM Larry Garfield <la...@garfieldtech.com> wrote:
> Greetings, Internalians. > > Some months back I proposed an RFC for short functions. > > https://wiki.php.net/rfc/short-functions > > After some discussion, I put it on hold to ensure that it was compatible > with the other discussion floating about around an alternate syntax for > multi-line closures that did auto-capture. It's important that the syntax > of both proposals is consistent. > > Nuno Maduro and i have talked recently and worked out the syntax that is > consistent between both proposals. That takes 'fn' off the table for > short-functions, for reasons discussed in both RFCs. > > To that end, I offer: > > 1) The updated short-functions RFC: > https://wiki.php.net/rfc/short-functions > > 2) A new RFC, code by Nuno, for auto-capturing multi-statement closures: > https://wiki.php.net/rfc/auto-capture-closure > > These are separate RFCs and at this time we plan to send them to separate > votes, but I list them together to demonstrate that they have been > developed in a mutually-compatible way. > > Further details in the auto-capture-closure RFC. > Hey Larry, I'm generally in favor of supporting auto-capture for multi-line closures. I think that extensive experience in other programming languages has shown that auto-capture does not hinder readability of code, and I don't see any particular reason why the effects in PHP would be different. I also think there is value in having a consistent syntax for closures -- currently, you have two options, and may need to switch between them as you add or remove code. There are some caveats though, which this RFC should address: 1. Auto-capture in arrow functions works by-value. This is sufficient for the purpose of single-line arrow functions, where you would be hard-pressed to perform any meaningful state mutation. For multi-line closures, it becomes much more likely that you want to modify a value from the outer scope. It should be possible to do this without switching to the function() notation. I do believe that by-value capture is the correct default, and should remain as such, but there should be an opt-in for by-reference capture. My suggestion would be to allow use(&$count) on fn(), which allows capturing certain variables by reference rather than by value. An alternative that has previously been discussed is to allow changing the default capture mode using something like use(&), but I believe it would be better if variables captured by reference had to be spelled out explicitly. 2. For much the same reason, capture analysis for arrow functions is very primitive. It basically finds all variables that are used inside the closure body and tries to import them, silently failing if they are not available in the outer scope. For multi-line closures, this would commonly end up importing too many variables. For example: fn() { $tmp = foo(); bar($tmp); return $tmp; } Here, there is no need to import $tmp from the outer scope, but a naive implementation (which I assume you're using) will still try to capture it. Now, this has two effects: a) Performance, as we're trying to capture unnecessary variables. This may be negligible, but it would be good to at least quantify. I would rather there not be recommendations along the line of "you should use function() for performance-critical code, because it's faster than fn()". b) Subtle side-effects, visible in debugging functionality, or through destructor effects (the fact that a variable is captured may be observable). I think it nothing else, the RFC should at least make clear that this behavior is explicitly unspecified, and a future implementation may no longer capture variables where any path from entry to read passes a write. Regards, Nikita