PHP8.5でパイプライン演算子が使用可能になったの記事を書いていて、そういえばJavaScriptにもパイプラインが来るって話を前やったような気がするなあと思い返したら8年前でした。
それだけ時間がたっているのだから少しは進んだのかと思えば、現在のステージは8年前と全く変わらないStage2のままです。
proposalの最終commitも2023/12/01であり、完全に停滞してしまっています。
いったいどうなっているのでしょうか?
パイプライン演算子のスタイル
とりあえず前提としてパイプライン演算子のスタイルを解説しておきます。
パイプライン演算子のスタイルはざっくり2種類が存在します。
引数を明示しないF#スタイルと明示するHackスタイルです。
let addOne x = x + 1;
let add x y = x + y;
1
|> addOne
|> add 2
関数addの引数は2つのはずなのに1つしか渡していません。
addOneに至っては引数が存在しません。
パイプライン演算子を使った場合、前段の出力が次の関数の引数に暗黙的に突っ込まれることになります。
このスタイルはポイントフリースタイルと呼ばれ、bashでもおなじみですね。
他にもHaskellやElmといった関数型出身の言語はこちらを採用していることが多いようです。
function addOne(int $x){ return $x + 1; }
function add(int $x, int $y){ return $x + $y; }
1
|> addOne(...)
|> add(? ,2)(...);
Hackスタイルでは全ての引数を明示する必要があります。
PHPもこちらを採用しています。
まあ単純にパイプライン演算子だけを見るならF#スタイルの方がメリットが多いわけですが、PHPの場合はパイプライン演算子を後付けで組み込んだので諸々問題が出かねないこと、これまでのスタイルと相容れない形式であることから後者の採用に至っています。
JavaScriptも、後者のHackスタイルを選択しました。
したのですが、その結果として関連スレッドが大いに盛り上がることになりました。
このあたりは詳しく解説してくれてる人がいるので、そちらを見てみるとよいでしょう。
https://www.kabuku.co.jp/developers/pipe-operator-debate
https://zenn.dev/yuku/articles/b169ac62ac3271
ただ上記記事では書かれていないのが、どうして最終的にHackスタイルが選ばれたのかの理由です。
これはF#スタイルの提案が却下されてHackスタイルが受理されたからなのですが、ではなぜ却下されたかというと、その大きな理由がJavaScriptエンジン開発者の中の人が反対していることです。
F#スタイルを実装するとJavaScriptエンジンのパフォーマンスが落ちてしまうから採用しないよ、採用されたとしても実装しないよ、ということだそうです。
TC39はブラウザベンダーの中の人も入っているとは言え所詮外部団体に過ぎないので、いくら素晴らしい仕様を決めたところでブラウザ側が相手にしないなんてことが十分あり得るわけです。
さてIssueを盛大に盛り上げたあと、パイプライン演算子の進捗はぱたりと途絶えてしまいました。
リポジトリは2022年8月で止まったままです。
そんなわけで人々の記憶からも忘れ去られつつあるわけですが、2025年4月時点でこの提案がどこまで進んだか、TC39の中の人による進捗が投稿されていたことに先日気が付きました。
Official changes thread 2025/04/08
2025年です。
2022年の最後の更新から3年が経ちました。
JavaScriptのパイプ演算子の現状はどうなったのでしょう?
Committeeの多くは依然として暗黙的・ポイントフリープログラミングに強く反対しています。
もっとも強い反対は、エンジン開発者からのものです。
Prior difficulty persuading TC39 about F# pipes and PFA #221のチケットに、この点についての詳細が記されています。
結果として、F#・Elixirスタイルのパイプは成立する見込みはなく、部分適用は停滞したままであり、関数合成は撤回されました。
Hackスタイルのパイプは、依然として実現可能なパイプの唯一の選択肢のままです。
ここ数年、Committeeの多くは新しい構文に対して厳しさを増してきています。
理由は複雑さではありません。
パイプ演算子は、TC39全体においても極めてシンプルな構文です。
全ての新しい構文の提案は、Committeeの厳しい目にさらされます。
パイプ演算子の単純さは、逆に欠点であるとみなす人すら存在します。
何故ならば、パイプ演算子はユーザ空間で対応できないような新しい機能を導入することはないからです。
パイプ演算子は、ブラウザのコア機能として実装するのではなくツール層として実装されるJSSugarのメインターゲットのひとつとして捉えられています。
しかしJSSugarのアイデアはいまだ途上であり、当分は先のことです。
これは、新しい構文の導入がいかに困難になっているかを表す事例のひとつです。
従ってパイプ演算子の推進派は、TC39など標準化の場で容易に達成できそうな方針、すなわち新しい構文を伴わない提案に集中することにしました。
この数年間Committeeの議論は進まず、適切なトークンを定めることすら行き詰っていました。
特に当時のtuples/records、現在のcompositesなど他の提案との兼ね合いでトークンの取り合いになっていました。
もしcompositesが構文に#を使わないことに決定すれば、パイプ演算子がそれを利用できるということになり、大きな前進を意味します。
またCall-thisなど類似した提案との兼ね合いも決められていません。
(Call-thisも同じように、有用性の疑問符やエコシステム分裂のリスクといった懐疑的な意見に晒されています)
このため、エンジンの負荷を高めず、パイプ演算子とCall-thisの相乗効果を高めるようにしたFunction.prototype.demethodizeを提案する予定です。
一部メンバーは、パイプ演算子がコーディングにどのような影響を与えるか、特に一時変数に比べてどう変わるか、についてより多くの研究・証拠を求めています。
実世界の例やコードベースによると、開発者は一時変数を作るよりも、読みづらい深いネストを作りがちな傾向があると私は考えています。
しかし、より実証的な証拠があるほうが望ましいでしょう。
2025年3月に行われたTG5ワークショップでは、再検討すべき提案のひとつとしてパイプ演算子が取り上げられました。
ボランティアの時間が許す限り、パイプ演算子に関する新たな研究を進めていきます。
次の課題は、@codehagが2019年ごろに主導したパイプ演算子についてのユーザビリティの調査結果をレビューすることです。
非常に時間がかかったことを謝罪します。
しかしボランティアによる作業という性質上、仕方のないことです。
パイプ演算子で記号#が使用できるようになるかもしれない可能性を踏まえ、今年後半に再度アップデートを行う予定です。
tc39/tg5は、新たな学術的ユーザビリティ調査に興味のあるボランティアを歓迎しています。
パイプ演算子は、新提案JSSugarシステムの最初のテストケースの一つになる可能性があります。
全体として、今年ステージ4に到達することはありません。
まとめ
一言でまとめると、何も進んでないってことでは?
感想
関連するトピックを軽く眺めた感想ですが、実に自転車置き場だねと。
中の人がF#スタイルは無理だと言っているのに、一部F#狂信者が事情を顧みずに喚き散らしたせいで開発者のやる気がなくなって結果として放置された、というふうに見えます。
そしてもちろん「パフォーマンスの問題なんて俺がかわりにどうにかしてやるよ」という人は現れませんでした。
まあ外からちょっと眺めただけの部外者の感想なので、中の人としては別の主張もあるのかもしれませんが、F#派にとってはHack実装されるくらいならパイプラインなんて無い方がいいらしいので、こうやって停滞するのも本望なのかもしれませんね。