Короткие замыкания в PHP

Короткие замыкания в PHP

или стрелочные функции

Короткие замыкания, также называемые стрелочными функциями, являются способом написания более коротких анонимных функций в PHP. Эта полезн

Вот как они выглядят:


// коллекция Post объектов
$posts = [/* … */];

$ids = array_map(fn($post) => $post->id, $posts);

Раньше писали так:


$ids = array_map(function ($post) {
return $post->id;
}, $posts);

Итак, что можно сказать про короткие замыкания.

  • Они начинаются с ключевого слова fn
  • Они доступны с PHP 7.4
  • Они могут иметь только одно выражение, которое является оператором return
  • Ключевое слово return можно опустить
  • Аргументы и возвращаемые типы могут быть подсказаны

Более строго типизированный способ написания приведенного выше примера может быть таким:


$ids = array_map(fn(Post $post): int => $post->id, $posts);

Стоит упомянуть еще пару вещей:

  • Оператор спреда (...) разрешен
  • Разрешены ссылки как на аргументы, так и на возвращаемые значения.

Если вы хотите вернуть значение по ссылке, следует использовать следующий синтаксис:


fn&($x) => $x

Короче говоря, короткие замыкания обеспечивают ту же функциональность, которую вы ожидаете от обычных замыканий, за исключением того, что в теле функции допускается только одно выражение.

Нет многострочности

Вы правильно прочитали: короткие замыкания могут иметь только одно выражение. Это означает, что они исключают в них несколько строк.

Аргументация такова: цель коротких замыканий - уменьшить многословие. fn конечно короче чем function во всех случаях. Однако Никита Попов, создатель RFC, утверждал, что если вы работаете с многострочными функциями, то с помощью коротких замыканий можно получить меньше кода.

В конце концов, многострочные замыкания по определению уже более многословны; поэтому возможность пропустить два ключевых слова ( 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;
}


В общем, короткие замыкания являются хорошей фичей, хотя есть еще хотелки, которые можно улучшить. Самой желанной из них, вероятно, являются появление многострочных коротких замыканий.


UPD 05.05.2019

Кстати, разработчики фреймворка Laravel быстро отреагировали на появление коротких замыканий в PHP 7.4 и сделали их будущую поддержку, пример:


// Current
$users->map(function($user) {
return $user->first_name.' '.$user->last_name;
});

// with arrow function:
$users->map(
fn($user) => $user->first_name.' '.$user->last_name
);



Сергей Мухин

Веб-разработчик со стажем программирования более 6 лет, постоянно учусь, люблю делать новые проекты.

Есть вопросы?

Я почти всегда в режиме онлайн

Связаться со мной