👋

【PHP8】アロー関数で複数行書けるようにしたいよねっていうプルリク

2020/11/16に公開2

PHP7.4で導入された便利機能アロー関数、みんな使ってますか?
私はあんまり。

$x = 1;
$fn = fn($y) => $x+$y;

$fn(1); // 2
$fn(10); // 11

やはり1文しか書けないのと括弧で括れないので微妙に使い辛いんですよね。
ちょっとした確認とかにぱっと書けるのはいいのですが、1文ではあまり本格的な関数を書くことができません。
それなら普通に関数書くわってなりがちです。

ということでなんか{}で括って複数行書けるプルリクが来ていました。
提出者のNuno MaduroLaravel ZeroとかPestとか作っていて実績がある人です。
またプルリク自体の評価や注目度もとても高いです。

Adds support to multi-line arrow functions

みんなも知ってのとおり、PHP7.4でアロー関数が導入されました。
そしてこのプルリクエストでは、アロー関数に複数行の記述を許可します。
例を見てみましょう。

$users = [/** */];
$guestsIds = [/** */];
$repository = /** */;

$guests = array_filter($users, fn ($user) {
    $guest = $repository->findByUserId($user->id);

    return $guest !== null && in_array($guest->id, $guestsIds);
});

このプルリクはPHP8.1での導入を目指していて、近日中にRFCを立てる予定です。

この機能の利点は、以下のように書くことができることです。

-$values = array_filter($values, function ($value) use ($first, $second, $third, $four) {
+$values = array_filter($values, fn ($value) {

・複数行アロー関数は、外部スコープの変数値を直接参照できるのでuseキーワードが必要ありません。
・それに、fn (/** */) {は大抵function (/** */) use (/** */) {よりシンプルです。

PHPコアへのプルリクは初めてなので、なにか改善すべき点があったら教えてください👍🏻

テストコード

$foo = fn() {};
var_dump($foo()); // null

$foo = fn() => 1;
var_dump($foo()); // 1

$foo = fn() { return 2; };
var_dump($foo()); // 2

$foo = fn($x) => $x;
var_dump($foo(3)); // 3

$foo = fn($x) { return $x; };
var_dump($foo(4)); // 4

$foo = fn($x, $y) => $x + $y;
var_dump($foo(4, 1)); // 5

$foo = fn($x, $y) { return $x + $y; };
var_dump($foo(5, 1)); // 6

$var = 7;
$foo = fn() => $var;
var_dump($foo()); // 7

$var = 8;
$foo = fn() { return $var; };
var_dump($foo()); // 8

$foo = fn($var) => $var;
var_dump($foo(9)); // 9

$foo = fn($var) { return $var; };
var_dump($foo(10)); // 10

$var = 11;
$foo = fn() => ++$var;
var_dump($var); // 11
var_dump($foo()); // 12
var_dump($var); // 11

$var = 13;
$foo = fn() { return ++$var; };
var_dump($var); // 13
var_dump($foo()); // 14
var_dump($var); // 13

$var = 14;
var_dump((fn() => fn() => $var)()()); // 14

$var = 15;
var_dump((fn() => function() use($var) { return $var; })()()); // 15

$var = 16;
var_dump((fn() { return fn() { return $var; }; })()()); // 16

var_dump((fn() { return fn() {}; })()()); // null

これぞ求めていたアロー関数ってかんじですね。
最後のような使い方はやめてくれよって思いますが。

レビュー

いつものNikita
もうちょっと変数キャプチャを考える必要があります。
以下では外部の$xをバインドする必要はありません。

$x = 1;
$fn = fn() {
    $x = 2;
    return $x;
};

他にも幾つか疑問や懸念が来ています。

気になる構文

PHPでは素の{}にスコープがないんですよね。

$x = 1;
{
  $x++;
}
var_dump($x); // 2

ここにアロー関数が並ぶとこうなります。


$x = 1;
{$x++;}
var_dump($x); // 2

$x = 1;
(fn()=>{$x++;})();
var_dump($x); // 1

どうなんだろう。

まあ、現時点で既にこんなだから、今さら気にすることでもないか。

$x = 1;
(fn()=>$x++)();
var_dump($x);

感想

近日中に作ると言っておきながらRFCはまだ見当たりません。
またRFCやメーリングリストでは、構文や変数キャプチャ周りについて、色々と議論が発生しているようです。

とはいえ評価も高いし総論反対もほとんどいないようなので、PHP8.1か、まあ遅くても8.2あたりで入るのではないかなとは思います。
これで本格的にアロー関数を導入できそうですね。

Discussion

Kaido IwamotoKaido Iwamoto

タイトルにPHPという言葉を入れた方がいいんじゃないかと思いました。

rana_kualurana_kualu

あーzennって投稿一覧にタグ出てこないんですね。
追加しました、ありがとうございます。