Re: [RFC] Short Closures 2, aka auto-capture take 3
| From: | Marco Pivetta | Date: | Thu, 09 Jun 2022 19:28:59 +0000 |
| Subject: | Re: [RFC] Short Closures 2, aka auto-capture take 3 | ||
| References: | 1 2 3 4 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-117894@lists.php.net to get a copy of this message | ||
On Thu, 9 Jun 2022 at 21:27, Nikita Popov <nikita.ppv@gmail.com> wrote:
> On Thu, Jun 9, 2022 at 8:15 PM Arnaud Le Blanc <arnaud.lb@gmail.com>
> wrote:
>
>> Hi,
>>
>> On jeudi 9 juin 2022 18:46:53 CEST Marco Pivetta wrote:
>> > ## nesting these functions within each other
>> >
>> > What happens when/if we nest these functions? Take this minimal example:
>> >
>> > ```php
>> > $a = 'hello world';
>> >
>> > (fn () {
>> > (fn () {
>> > echo $a;
>> > })();
>> > })();
>> > ```
>>
>> Capture bubbles up. When an inner function uses a variable, the outer
>> function
>> in fact uses it too, so it's captured by both functions, by-value.
>>
>> This example prints "hello world": The inner function captures $a from
>> the
>> outer function, which captures $a from its declaring scope.
>>
>> This is equivalent to
>>
>> ```php
>> (function () use ($a) {
>> (function () use ($a) {
>> echo $a;
>> })();
>> })();
>> ```
>>
>> > ## capturing
$this
>> >
>> > In the past (also present), I had to type static fn () =>
>> > ... or
>> `static
>> > function () { ...` all over the place, to avoid implicitly binding
>> $this
>> > to a closure, causing hidden memory leaks.
>> >
>> > Assuming following:
>> >
>> > * these new closures could capture $this
>> > automatically, once detected
>> > * these new closures can optimize away unnecessary variables that
>> aren't
>> > captured
>> >
>> > Would that allow us to get rid of static fn () {
>> > declarations, when
>> > creating one of these closures in an instance method context?
>>
>> It would be great to get rid of this, but ideally this would apply to
>> Arrow
>> Functions and Anonymous Functions as well. This could be a separate RFC.
>>
>
> I've tried this in the past, and this is not possible due to implicit
> $this uses. See
>
> https://wiki.php.net/rfc/arrow_functions_v2#this_binding_and_static_arrow_functions
> for a brief note on this. The tl;dr is that if your closure does "fn() =>
> Foo::bar()" and Foo happens to be a parent of your current scope and bar()
> a non-static method, then this performs a scoped instance call that
> inherits $this. Not binding $this here would result in an Error exception,
> but the compiler doesn't have any way to know that $this needs to be bound.
>
> Regards,
> Nikita
>
Hey Nikita,
Do you have another example? Calling instance methods statically is...
well... deserving a hard crash :|
Marco Pivetta
https://twitter.com/Ocramius
https://ocramius.github.io/