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