Анонимные функции в PHP
Относительно недавно в ПХП появился новый способ создания анонимных функций. Раньше мы писали array_filter($strs, 'strlen'), теперь можем писать array_filter($strs, strlen(...)).
В первом случае у нас указывается строка, во втором — анонимная функция. Последнее намного лучше, конечно, потому что помогает строгой типизации и лучше понимается редакторами кода.
Когда этот синтаксис появился, в моей голове он стал частным случаем стрелочного синтаксиса. В самом деле, ведь fn($t) => sin($t) и sin(...) — это одно и то же. Но недавно я понял, что у второго синтаксиса есть побочный эффект. По какой-то причине раньше мне это было не очевидно.
Если посмотреть на код ниже, всё должно стать понятно, но если нет, то я поясню.
Тут мы видим класс, конструктор которого печатает код, находящийся в строке, которая его вызвала. Ниже класса создаются две анонимные функции, одна — стрелочная через fn(), вторая — через многоточие.
Этот код позволяет проиллюстрировать разницу.
В случае создания анонимной функции через fn(), конструктор будет вызван каждый раз заново на любой вызов функции.
В случае синтаксиса с многоточием, конструктор будет вызван сразу при создании, а при вызове, в том числе многократном, он вызываться не будет.
То есть каждый способ имеет особенности, которые надо учитывать.
class Sample
{
public function __construct()
{
$bt = debug_backtrace();
['line' => $line, 'file' => $filename] = end($bt);
echo file($filename)[$line - 1];
}
public function method(): void
{
}
}
$a = fn() => (new Sample)->method(); // не выведет ничего
$b = (new Sample)->method(...); // выведется «$b = (new Sample)->method(...);»
$a(); $a(); // выведется «$a(); $a();» два раза
$b(); $b(); // не выведет ничего
static fn ($v) => sin($v)
Да, ваша правда, но в данном случае мне показалось, что это лишняя подробность.