On 31/03/2025 21:38, Ilija Tovilo wrote:
> Hi everyone
>
> A few years ago, an RFC was proposed to introduce special syntax for
> self-referencing closures, mainly used for implementing recursion.
>
> https://wiki.php.net/rfc/closure_self_reference
>
> The proposed solution allows specifying a variable that will be
> assigned the closure object on function entry.
>
> $fibonacci = function (int $n) as $fn {
> if ($n === 0) return 0;
> if ($n === 1) return 1;
> return $fn($n-1) + $fn($n-2);
> };
>
> This is essentially already possible through a by-reference capture.
>
> $fibonacci = function (int $n) use (&$fibonacci) { ... };
>
> This cannot be a by-value capture because by the time the closure is
> created and variables are bound, $fibonacci is not assigned yet. The
> downside of by-reference capturing is that if $fibonacci is
> accidentally reassigned, the reference within the closure is also
> changed.
>
> However, I consider a language change largely unnecessary. Instead,
> this may be solved with a very simple static function:
> Closure::getCurrent().
>
> $fibonacci = function (int $n) {
> if ($n === 0) return 0;
> if ($n === 1) return 1;
>
> $self = Closure::getCurrent();
> return $self($n-1) + $self($n-2);
>
> // Or
> return Closure::getCurrent()($n-1) + Closure::getCurrent()($n-2);
> };
>
> Another suggestion was to introduce a magic constant __CLOSURE__.
> However, this would be misleading, given it can refer to different
> closure instances, thus not actually being constant.
>
> You can find the implementation here:
> https://github.com/php/php-src/pull/18167
>
> I picked the name Closure::getCurrent() to be consistent with
> Fiber::getCurrent(). Contrary to fibers, calling Closure::getCurrent()
> from non-closures is nonsensical and thus disallowed, resulting in an
> Error exception. It will only succeed when called directly from
> closures. It will not recurse the call stack.
>
> Do you have thoughts or concerns with this solution? If not, I'm
> planning to merge it into master in a few weeks.
>
> Ilija
PHP now officially better than JavaScript, which had arguments.callee
since inception, but was then deprecated without replacement.