PHP で複数行の短いクロージャが必要な理由

in Vlog

(jp) =

PHP 8.1 はすでにかなりうまく形になっていますが、追加してほしい機能が 1 つあります。それはまだ議論されています。それは、複数行の短いクロージャです。 RFC ではこれらを「自動キャプチャ マルチステートメント クロージャ」と呼んでいますが、多少短い名前を使用してもかまわないことを願っています。

アクティブにサポートされている PHP バージョンを使用している場合は、短いクロージャー (別名「アロー関数」) については既にご存じでしょう。 そして、最も重要なことは、それらの最大の欠点の 1 つです。戻り値としても使用される 1 行の式しかサポートしていません。

複数行の短い閉鎖 RFC による ヌーノラリー 私が思うに、エレガントな方法でその問題を解決することを目指しています。

ただし、この RFC に懐疑的な人もいます。私は彼らの議論に対処し、なぜ追加する価値があると思うのかを共有したいと思います。 最初に、RFC とは何かを説明します。 これは提案であり、まだ PHP に追加されていないことに注意してください。

簡単に復習すると、現在の PHP のアロー関数は次のようになります。

$getTitle = fn (Post $post) => $post->title;

そして、これはRFCが提案するものです:

$date = now();

$getSlug = fn (Post $post) 
    $slug = Str::slug($post->title);
    
    return $date . $slug;

複数行の短いクロージャについて注意すべき重要な点が 2 つあります。

  • 彼らは必要なく上位スコープの変数にアクセスできます use; と
  • 彼ら しないでください 複数行のクロージャには複数の式が存在する可能性があるため、最後の式を自動的に返します。

すでにお気づきかもしれませんが、RFC では、クロージャーを作成する方法に洗練された種類の対称性が導入されています。

  • 一方では functionfn、最初のものは外部から変数を自動キャプチャしませんが、2番目のものはそうします; と
  • 一方、 また =>、中括弧を使用すると、複数の行を書くことができますが、 => 1 つの式のみを受け入れますが、それを返します。

この対称性により、次のすべてのコード サンプルが可能であり、すべての動作が少し異なります。

これは、複数の行を持つ、外側のスコープを自動キャプチャしないクロージャーです。

$date = now();

$getSlug = function (Post $post) use ($date) 
    $slug = Str::slug($post->title);
    
    return $date . $slug;

次に、外側のスコープをキャプチャしてすぐに結果を返すクロージャ:

$date = now();

$getSlug = fn (Post $post) => $date . Str::slug($post->title);

そして最後に — RFC によって提案された — 外側のスコープをキャプチャするが、複数の行を許可するクロージャ:

$date = now();

$getSlug = fn (Post $post) 
    $slug = Str::slug($post->title);
    
    return $date . $slug;

カウントしている場合は、1 つのオプションがまだ不足していることがわかります。それは、外側のスコープを自動キャプチャせず、すぐに値を返すクロージャーです。

$date = now();

$getSlug = function (Post $post) use ($date) 
    => $date . Str::slug($post->title);

RFC は、この最後のものを将来の追加の可能性として挙げていますが、現在はカバーしていません。


背景情報を整理したところで、一部の人々がこの変更を好まない理由について、いくつかの反論を見てみましょう。

# 外側のスコープを自動キャプチャすると、バグが発生する可能性があります

一部の人々は、外部スコープから変数を自動キャプチャすることについて懸念を表明しています。特に、長期的にはコードが不明確になり、バグが発生する可能性があるためです。

私はその恐怖に反対するいくつかの議論を持っています.

まず、自動キャプチャは、現在の短いクロージャーで PHP によって既にサポートされています。この RFC については、それを変更するものは何もありません。 アロー関数 RFC は、徹底的な議論の末、賛成 51 票、反対 8 票で可決され、それ以来、多くのプロジェクトで広く使用されています。 あなたがそれを恐れているかどうかにかかわらず、この特定の行動が大多数の人々によって望まれているという明確な兆候.

ニキータもこの意見を共有しています:

私は通常、複数行のクロージャの自動キャプチャをサポートすることに賛成です。 他のプログラミング言語での豊富な経験から、自動キャプチャがコードの可読性を妨げないことが示されていると思います。また、PHP での効果が異なる特別な理由は見当たりません。 — https://externals.io/message/113740#114239

外側のスコープを自動キャプチャすることは、コーディングの好ましい方法ではないかもしれませんが、それはアイデアを却下する必要があるという意味ではありません。 行う このスタイルを好む。

恐怖はプログラミング言語の設計の原動力であってはならず、代わりに事実に目を向けるべきです。

tpyoに気づきましたか? PR を送信して修正することができます。 このブログの最新情報を知りたい場合は、私をフォローしてください。 ツイッター または私のニュースレターを購読してください:

# 値渡しまたは参照渡し

外側のスコープの変数は参照ではなく常に値によってキャプチャされると RFC が言っていることは正しいと思います。 これは、クロージャ内から外部スコープ変数の値を変更できないことを意味します — これは良いことです。

これは混乱を招くと人々は主張するかもしれません。 行う 外部スコープ変数を変更したいですか? これが良いアイデアであるかどうかについて議論することはできますが、PHP は既に答えを持っているので問題ではありません — 先ほど話した対称性を覚えていますか?

参照渡しが必要な場合は、アクセスしたい変数を具体的に指定する必要があります。 function 以下を許可します。

$date = now();

$getSlug = function (Post $post) use (&$date) 
    $date = now()->addDay();
    
    

この RFC が、 functionfn. 混乱を招くことはありません。 それどころか、PHP の構文に一貫性と明快さをもたらします。

#獲得できるスペースはほとんどありません

書いている文字の量に関しては、得られるものがほとんどないため、複数行の短いクロージャーを追加する必要はないと主張する人もいます。 外側のスコープの値に依存していない場合はそうかもしれませんが、正直なところ、何文字書くかは問題ではありません。

この RFC により、言語の構文がより一貫したものになり、一貫した言語によってプログラミングが容易になります。

コードを書くとき、変更に煩わされたくない fnfunction 前の行ではなく、突然 2 行で記述する必要があるクロージャーをリファクタリングするとき。

些細なことのように思えるかもしれませんが、日々の開発者の生活に影響を与えるのは、これらの詳細です。 そして、それこそが成熟した言語であるべきではないでしょうか? プロパティの昇格、名前付き引数、列挙型、属性、一致演算子などの機能を見てください。動作する PHP コードを記述するためにこれらの機能は「必要ない」と主張することもできますが、それでも日常生活は改善されます。あなたのことも願っています。

#過去にしがみつく

最後に、変更に対処するのが難しいと感じる人もいるかもしれません。RFC に投票する場合は、その質問を自問する必要があります。 はい、特定の機能の必要性を認識していないかもしれませんが、自分自身に投票するだけでなく、PHP コミュニティに対して責任があります。 これには、プロジェクトやチームだけではありません。

クロージャーが現在、外部スコープから変数を自動インポートしない理由を知っていますか? 慣れてきたかもしれませんが、なぜ12年前にこのように設計されたのか知っていますか? Larry がメーリング リストのアーカイブを調べたところ、3 つの理由があることがわかりました。 use 最初に紹介されました:

  • 外部スコープの変数が自動キャプチャされた場合、パフォーマンス上の懸念がありました — 今日ではもはや関係のない懸念です。
  • これは、予期しない参照による値の受け渡しを回避するために使用されました — これも、常に値による受け渡しを使用しているため、問題ではありません。 と
  • これにより、ユーザーは変数を値または参照で明示的にキャプチャできるようになりました。 functionfn.

過去 10 年間、変数を自動インポートしないクロージャーに慣れてきたかもしれませんが、この動作は必要に応じて追加されただけであることを覚えておいてください。 明示的なキャプチャのみを使用するというすべての議論は、時間の経過とともに無効になりました。これは、PHP がさらに成熟していることを示す素晴らしい兆候です。

tpyoに気づきましたか? PR を送信して修正することができます。 このブログの最新情報を知りたい場合は、私をフォローしてください。 ツイッター または私のニュースレターを購読してください:

以上のことを踏まえて、Nuno と Larry が RFC の投票を開始することを楽しみにしています。 PHP 8.1 の機能凍結は 2021 年 7 月 20 日に予定されています。 そのため、詳細を確定するにはまだ時間がかかります。 RFC に投票する場合は、全体像を把握できることを心から願っています。これは、多くの人々の開発者の生活に大きな影響を与える RFC の 1 つだからです。

//platform.twitter.com/widgets.js

関連記事

前の投稿
10種類の犬耳
次の投稿
世界記録の金魚:世界最大の金魚を発見