В PHP 7.4 войдут стрелочные функции (сокращенная запись анонимных функций)
Голосование по сокращенному синтаксису для функций завершено (51 «за», 8 «против»).
Было:
$result = array_filter($paths, function ($v) use ($names) {
return in_array($v, $names);
});
Стало:
$result = array_filter($paths, fn($v) => in_array($v, $names));
Подробности под катом
Новый синтаксис такой:
Синтаксис
fn(список_параметров) => возвращаемое_выражение
В сигнатуре стрелочной функции, как и в обычной функции, можно указывать типы, дефолты и прочее
fn(array $x) => $x;
fn(): int => $x;
fn($x = 42) => $x;
fn(&$x) => $x;
fn&($x) => $x;
fn($x, ...$rest) => $rest;
Внимание! Появилось новое ключевое слово fn
, а это означает обратную несовместимость!
Другие (отброшенные) идеи по синтаксису
Рассматривались варианты:
// невозможно реализовать, путаница с элементами массивов в некоторых случаях
($x) => $x * $y
// так можно сделать, но слишком много фигурных скобок, особенно для вложенных функций
{ ($x) => $x + $y }
// так сделано в языке Hack; но слишком сложно для текущего парсера
($x) ==> $x * $y
// нереализуемо, путаница с получением свойств объекта
($x) -> $x * $y
// сейчас парсер это понимает как $x-- > $x*$y
$x --> $x * $y
// так сделано в Rust, но читабельность спорна
|$x| => $x * $y
и некоторые другие
Замыкание переменных
Важно! В отличие от предыдущих версий php, где надо было явно задавать замыкаемые переменные оператором use, стрелочная функция неявно замыкает на себе весь родительский скоуп.
Вот эквивалентные записи:
$y = 1;
$fn1 = fn($x) => $x + $y;
$fn2 = function ($x) use ($y) {
return $x + $y;
};
Переменная $this замыкается точно также, как и любая другая переменная. Если это нежелательное поведение, можно его запретить ключевым словом static.
class Test {
public function method() {
$fn = fn() => var_dump($this);
$fn(); // object(Test)#1 { ... }
$fn = static fn() => var_dump($this);
$fn(); // Error: Using $this when not in object context
}
}
Замыкание переменных в стрелочных функциях происходит по значению (в отличие от языка Go, например). Т.е. изменение переменных внутри функции не приведет к изменению переменной в родительском скоупе.
Выводы
Код стал значительно компактнее, и хотя не такой компактный, как в javascript и некоторых других языках, но всё же писать будет значительно приятнее:
$result = Collection::from([1, 2])
->map(fn($v) => $v * 2)
->reduce(fn($tmp, $v) => $tmp + $v, 0);
echo $result; //6
В отличие от некоторых других языков стрелочные функции в php не поддерживают несколько statements, разделенных через символ ;
, потому что это (по мнению авторов RFC) противоречит идее сокращенного синтаксиса. Возможно это будет пересмотрено в будущем.
Мы обязательно детально обсудим стрелочные функции в php в подкасте «Цинковый прод», так что не забудьте подписаться.
Ссылка на RFC: https://wiki.php.net/rfc/arrow_function