On Thu, Apr 29, 2021 at 12:00 AM Nuno Maduro <enunomad...@gmail.com> wrote:
> On Wed, 28 Apr 2021 at 15:31, Nikita Popov <nikita....@gmail.com> wrote: > >> 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 >> > > Hey Nikita, > > Concerning point 1: Agreed. Going to update both the pull request and the > RFC accordingly. > > Concerning point 2: Developing some sort of static analysis that can infer > what needs to be captured may be problematic. First, that won't be > consistent with the way auto-capture currently works in PHP (one-line short > closures). Second, what needs to be captured may be determined at runtime > (thinking about eval, variables names computed at runtime, etc). Of course, > I am willing to hear more thoughts on this. > Just to clarify: The way arrow functions *currently* work, capture analysis is performed statically. Only variables that are used directly in the arrow function will be captured. Variables used indirectly via include, eval, variable-variables, compact() etc are not captured. It would be possible to support this, but it isn't supported right now. Regards, Nikita