Hi

Am 2026-01-23 00:25, schrieb Theodore Brown:
Thank you for your work on this. However, I'm struggling to see the benefit
of this syntax over short closures given the examples in the RFC:

    $dates = [
        new DateTimeImmutable('now'),
    ];

$formattedDates = array_map(DateTimeImmutable::format($this: ?, "c"), $dates);

To provide some background on how this RFC came about: Arnaud and I were discussing my recent `array_map()` optimization (https://github.com/php/php-src/pull/20934) that compiles `array_map()` calls that either use FCC or PFA as the callback into the equivalent `foreach()` loop. The optimization skipped when an actual Closure is passed, since full-blown Closures come with all kinds of scope-related (edge) cases to consider, making it much more complicated. I noted that I believed that with PFA many `array_map()` cases could be handled without a full Closure and that it was unfortunate that it didn't work for “filling in the object itself”.

I then came up with the basic idea for the proposed syntax half-a-minute later and we figured it would at least be worth proposing it, since it mapped onto the existing PFA semantics in a fairly straight-forward fashion.

This saves only three characters compared to a short closure:

$formattedDates = array_map(fn(DateTimeImmutable $d) => $d->format("c"), $dates);

The return type would be missing in that snippet. And depending on your codebase's policy you might also need `static` in front of the short Closure. This might become less relevant with https://news-web.php.net/php.internals/129825, but personally I would still consider it a best-practice to be explicit.

Personally I also feel that short Closures have some “visual overhead” in that they don't feel like a simple “method reference”. It's quite similar to how PFA itself is technically redundant with short Closures, but allows to be more explicit with the intention (which enabled the optimization mentioned above).

Furthermore, duplicating the array's type isn't necessary when IDEs and static analysis can infer it, so short closures can usually be even more concise:

    $formattedDates = array_map(fn($d) => $d->format("c"), $dates);

This is true when the Closure is immediately consumed, but not when it's intended to be reused at a later point, e.g. with the Symfony Form example where the IDE / Static Analyzer needs some deeper knowledge about how the 2nd and 3rd parameter of `->add()` interact.

I also find the use of `$this` as a named argument confusing. It makes it appear as though the current class instance is somehow being passed to the
method, when this isn't the case.

That's fair. I would've hoped to just use `this:` without the `$`, but that comes with the breaking change for variadics mentioned at the bottom of the RFC.

A short closure is barely any longer, and makes it easier to add additional
logic when needed:

    'choice_label' => fn(Category $c) => $c->getName(),

    'choice_label' => fn(Category $c) => strtoupper($c->getName()),

Note: Return type + Static also missing here. And of course if more parameters would be passed, it would scale differently (since more types are required for proper autocompletion).

Best regards
Tim Düsterhus

Reply via email to