Pull to refresh

В PHP 7.4 войдут стрелочные функции (сокращенная запись анонимных функций)

Reading time2 min
Views21K

Голосование по сокращенному синтаксису для функций завершено (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


Больше полезного можно найти на telegram-канале о разработке "Cross Join", где мы обсуждаем базы данных, языки программирования и всё на свете!

Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
+35
Comments66

Articles

Change theme settings