Стрелочные функции, также называемые короткими замыканиями (short closures), станут хорошим способом писать чистый код в PHP. Такая форма записи будет полезной при передаче замыканий в такие функции как array_map
или array_filter
.
Пример:
// Коллекция объектов Post
$posts = [/* … */];
$ids = array_map(fn($post) => $post->id, $posts);
Раньше нужно было писать так:
$ids = array_map(function ($post) {
return $post->id;
}, $posts);
Кратко:
- Доступны с PHP 7.4
- Начинаются с ключевого слова
fn
- Могут иметь только одно выражение, также являющееся возвращаемым значением
- Не поддерживается
return
- Type-hintihg поддерживается в аргументах и возвращаемых значениях
Строготипизированный способ написания примера выше:
$ids = array_map(fn(Post $post): int => $post->id, $posts);
Еще две важные вещи:
- Поддерживается оператор переменного значения
- Поддерживаются ссылки, как для аргументов, так и для возвращаемых значений
Если вы хотите вернуть значение по ссылке, используйте следующий синтаксис:
fn&($x) => $x
Стрелочные функции реализуют ту же функциональность, которую вы ожидаете от нормальных замыканий, только содержат в себе одно выражение.
Нет многострочности
Вы верно прочитали: короткие замыкания могут содержать только одно выражение. Это означает что вы не можете иметь несколько строк в них.
Аргументация такова: целью коротких замыканий является снижение многословности. fn
, однозначно короче чем function
во всех смыслах. Пропуск ключевых слов function
и return
ничего не меняет, но позволяет сделать код более читаемым.
Согласны ли вы с этим мнением? В то же время при наличии нового синтаксиса для однострочных функций, существует множество многострочных, которым тоже бы не помешал подобный апгрейд.
Надеюсь, в будущем, появится RFC с коротким объявлениим и многострочных функций, но пока это только мои мечты.
Переменные из внешней области видимости
Еще одним существенным различием между короткими и нормальными замыканиями является то, что первые не требуют использования ключевого слова use
для получения доступа к данным из внешней области видимости.
$modifier = 5;
array_map(fn($x) => $x * $modifier, $numbers);
Важно отметить, что вы не можете изменять эти переменные. Значения связаны по значению, а не по ссылке. Это означает, что вы можете изменять $modifier
внутри короткого замыкания, но это не повлияет на переменную $modifier
находящуюся вне.
Единственное исключение — ключевое слово $this
, которое будет работать точно также, как и в нормальном варианте:
array_map(fn($x) => $x * $this->modifier, $numbers);
Будущие возможности
Я уже упоминал идею с многострочными короткими замыканиями выше. Еще одно полезное предложение — позволить использовать короткий синтаксис в классах, например для геттеров и сеттеров:
class Post {
private $title;
fn getTitle() => $this->title;
}
В целом, стрелочные функции это очень хорошая фича, хотя есть еще область для улучшения.
Есть ли у вас какие-либо мысли по этому поводу?