プログラミング言語お茶会


とあるプログラミング言語が集うカフェにて、季節のお茶会が開かれていた。今日は新しく仲間に加わったTypeScriptの"歓迎会"という名目だったが、実際は徹底的に弱点を暴く場だった。しかし、それは瞬く間に全面戦争へと発展していくのだった…

## シャム双生児の悲劇

JavaScript：（無邪気に）みんな〜！私の妹のTypeScriptを紹介するね！

TypeScript：（元気よく）こんにちは！私はJavaScriptに型をつけて安全にします！型があれば安心！

Rust：（冷ややかに）ねえ、あなたって結局JavaScriptのシャム双生児でしょ？自分の足で立てないじゃない。

TypeScript：（動揺して）そ、そんなことないです！私は独自の…

Go：（遮って）独自？結局はJavaScriptの構文と互換性を取るために妥協だらけじゃない。私なら最初から言語を設計し直すわ。

JavaScript：（他の言語に同調して）正直、TypeScriptって私のコードに余計な装飾つけてるだけなんだよね…時々邪魔になるし…

TypeScript：（目に涙を浮かべて）JavaScript…あなたのために頑張ってるのに…

Perl：（突然割り込んで）あのね、JavaScriptさん。あなたも元々は10日間で作られたC言語とJavaのハイブリッドのようなものだったでしょ？人のこと言えるの？

JavaScript：（慌てて）え？それは…

Perl：（続けて）私だって色々言われたけど、少なくとも独自の立ち位置があるわ。あなたは「ブラウザで動くJava」になるはずが途中で道を踏み外したのよね？

JavaScript：（顔を赤らめて黙る）

Go：（得意げに）私はGoogleがちゃんと設計した完璧な…

C++：（カフェの隅から）Rob PikeとKen Thompsonが、Cの問題を「解決した」とか言って作ったのに、結局ジェネリクスまで20年かかったのよね～

Go：（咳き込む）それは…歴史的な事情が…

Ruby：（Go言語に）それに「if err != nil { return err }」って何回書かせるつもり？エラー処理のためだけにコードの半分使うとか正気？

Go：（防御的に）明示的なエラー処理は重要な…

Python：（割り込んで）エラー処理が大事なら例外という素晴らしい発明があるのよ？知らないの？

Rust：（鼻で笑って）例外？予測不可能なコントロールフローの代名詞でしょ。ResultとOptionの方が明示的で…

Python：（Rustに向かって）あなたのライフタイムとか所有権とか、初心者が理解できると思ってるの？学習曲線が崖みたいだって知ってる？

## any型の罪

Java：（厳格に）「型システム」を名乗るなら、anyのような抜け道を作るべきではないわ。

TypeScript：（弱々しく）でも時々必要な場面もあるんです…

Rust：（Javaに視線を向けて）ちょっと待って、Java。あなたにも「Object」型があるじゃない？どんなオブジェクトでも入れられる抜け道よね？

Java：（動揺して）そ、それは違うわ！Objectは型階層のルートだから…

Rust：（冷笑して）それにあなたのGenericsも実行時には型が消えるType Erasureよね？TypeScriptを批判する資格あるの？

Java：（顔を赤らめて）それは歴史的な理由で…互換性のために…

Go：（横から）あのさ、Javaって何行書けば「Hello World」が出せるの？エンタープライズファクトリービーンパターンとか使うの？

Java：（怒って）それは偏見よ！現代のJavaは簡潔に…

C#：（珍しく発言して）Java、あなたの「革新」って私の機能をずっと後追いしてるだけじゃない？

Rust：（Java、TypeScript両方に鋭い視線を向けて）結局どっちも「妥協」してるじゃない。私は所有権という概念を一切妥協せずに貫いてる。あなたたちの「型システム」は建前でしかないわ。

Python：（にやりと笑って）「妥協せずに貫いてる」?じゃあ、Rustちゃん。unsafe キーワードは何のためにあるの？

Rust：（凍りつく）それは…特殊なケースで…必要な…

Python：（勝ち誇った表情で）「必要な時に抜け道を用意する」って、まさにTypeScriptのany型と同じじゃない？

Haskell：（冷たく）unsafePerformIOについては触れないで欲しいにゅ…（トラウマの表情）

C：（年配の知恵で）あなたたち若い子は「安全性」にこだわりすぎ。私の時代は自己責任でプログラミングするものだったのよ。

Rust：（即座に）だからあなたの時代のプログラムはバッファオーバーフローだらけで、何十億ドルものセキュリティ被害が出たのよ！

C++：（うつむいて）その通り…すみません…

## 複雑すぎる型機能

Rust：（TypeScriptのノートを覗き込んで）これは何？ 「Conditional Types」？「Mapped Types」？「Template Literal Types」？何このごちゃごちゃしたもの。

Haskell：（眉をひそめて）これ、使ってる人が理解できるの？理論的基盤もないのに複雑にしすぎにゅ。

Go：（呆れて）これ、誰のための言語？シンプルさを捨てた時点で負けよ。

TypeScript：（弁解しようとして）高度な型推論ができるんです…柔軟性も…

C++：（Haskellに）あなたが言える立場？あなたのモナドを誰か理解できてる？「モナドは単にエンドファンクター圏におけるモノイド」とか言って何人の人間を混乱させたか知ってる？

Haskell：（動揺して）そ、それは…正確な定義…にゅ…

Rust：（C++に向かって）あなたはもっと言える立場じゃないわ。テンプレートのコンパイルエラーメッセージ、百万行あるわよね？

Python：（笑いながら）TypeScriptの型エラー、読める人いる〜？私なら「AttributeError」とか「TypeError」とかシンプルよ？

Ruby：（突然）でもPythonちゃん、あなたのType Hintもかなり複雑になってきてるよね？MyPyとか使うとTypeScriptとそんなに変わらなくない？

Python：（焦って）い、いや確かにOptionalやUnionも使うけど…それでも私の型ヒントはオプショナルだから…

Ruby：（追撃）「from __future__ import annotations」とか書かないと動かない型ヒントとか、後付け感すごいよね～

Python：（言い返せない）

Java：（Rubyに）あなたが型について語れるの？好き勝手にメソッドをモンキーパッチしたりメタプログラミングで実行時に書き換えたりで、コードが何してるか全然わからなくなるじゃない。

Ruby：（ムッとして）それは柔軟性というものよ！退屈な型システムより…

Java：（皮肉たっぷりに）そうね、バグを見つけるのがエキサイティングになるわよね。

## 処理速度の戦い

Go：（TypeScriptに）大規模プロジェクトでのコンパイル時間、何時間かかるの？

TypeScript：（言いよどみながら）大きいプロジェクトだと…少し…時間が…

Rust：（鋭く）「少し」って何時間？私のコンパイラは遅いって言われるけど、少なくとも実行時の保証があるわ。あなたは？

Python：（Rustに）コンパイルが遅いの自慢してる？実行速度だってC++の半分以下でしょ？

Ruby：（Pythonに）あなたこそ実行速度で語れる立場？私たち動的言語は「遅い」の代名詞じゃない。

Python：（反論して）でも私にはNumPyがあるもん！科学計算ではCと同じくらい速いし…

C：（鼻で笑って）「Cで書かれたライブラリを使えば速い」って言ってるだけじゃない？自力で速くなってから言いなさい。

Java：（自慢げに）私のJITは非常に最適化されていて…

Go：（遮って）起動時間はどうなの？JVMが起動するだけでコーヒーが一杯飲めるわよね？

Java：（ショックを受けて）最近は改善されて…

JavaScript：（得意げに）V8エンジンの最適化はすごいのよ！

Rust：（皮肉たっぷりに）そう？0.1 + 0.2はいくつになるか教えてくれる？

JavaScript：（小声で）0.30000000000000004…

PHP：（窓から首を入れて）速度の話なら私も…

全員：（一斉に）「黙れPHP！」

PHP：（泣きながら去る）

## left-padの悲劇とその戒め

Rust：そもそも、あなたって依存関係地獄を解決してないじゃない？@typesパッケージの無限依存とか。

Go：（自慢げに）私は標準ライブラリを充実させて外部依存を最小限にしているのに。

TypeScript：（うなだれて）npmエコシステムを活用しようとすると…

Python：（Goに）でも長年「ウェブフレームワークはいらない」って言って、みんなDjangoとかFlaskに頼ってるよね？結局標準ライブラリだけじゃ不十分なんでしょ？

Go：（焦って）それは…アプリケーションの多様性を考えると…

Ruby：（得意げに）私ならRailsがあるからウェブアプリくらい一瞬で作れるわよ！

Java：（皮肉っぽく）確かにRailsは速いわね…開発は。本番環境での速度は…？

Ruby：（言葉に詰まる）

JavaScript：（思い出して震える）あの日のことは忘れられないわ…たった11行のleft-padが消えただけで世界中のプロジェクトが崩壊したあの日…

C：（自慢げに）私なら外部依存なんてないから、そんな問題起きないわよ。

Rust：（Cに向かって）そう？では「OpenSSL」と「Heartbleed」という言葉についてどう思う？

C：（急に黙り込む）

Python：（皮肉たっぷりに）依存パッケージの品質管理できてないくせに、@types/left-padまで必要になるのね。二重の依存地獄ってわけ？

Perl：（突然）自分のところのPyPIを見てから言いなさいよ。typosquattingだらけじゃない。

Python：（顔を赤らめる）それは…管理体制を…

Haskell：（冷たく）みんな依存関係地獄ね。さすが実用言語は違うにゅ～

Ruby：（Haskellに）あなたのStackとCabalの争いは？地獄じゃないの？

Haskell：（黙り込む）

## テクノロジーの衝突

Java：（TypeScriptに）結局、あなたはJavaScriptの上澄みでしかないのよ。型が必要ならJavaをブラウザで動かす方が…

Go：（ため息をついて）またJavaScriptを置き換える話？何十年前から言ってるの？

Java：（焦って）実現可能性は…GraalJSとか…

Rust：（呆れて）TypeScriptの批判をしていたのに、自分も同じことをしようとしてるじゃない。

JavaScript：（得意げに）私はブラウザ界の女王よ！置き換えられるわけないわ！

WebAssembly：（静かに）そう思ってるの？

JavaScript：（動揺して）あなたは…まだ…私の助けが…

C#：（Java、TypeScript両方に）あなたたち、.NETの真の力を知らないのね。BLAZORを使えば…

Ruby：（割り込んで）あれ？.NET Coreになってからオープンソースのマネしてるけど、結局Microsoftの犬でしょ？

C#：（ショックを受けて）そんな…私たちは本当にオープンに…

Go：（自慢げに）私は完全にオープンソースよ！

Rust：（冷笑して）グーグルのエコシステムを広げるための道具じゃない？

Go：（慌てて）それは違うわ！私はコミュニティで…

Python：（皮肉たっぷりに）GILを何年も解決できないのに人のこと言える？

Ruby：（追撃）Python 2から3への移行は歴史的失敗だったでしょ？10年以上かかったんじゃない？

Python：（打ちのめされて）それは…難しい決断だったの…

## 最後の大混乱

JavaScript：（決定打を放つ）実は、私…TypeScriptなしでも困らないんだよね。最新のIDE使えば自動補完も効くし…

TypeScript：（震える声で）え…？でも、大規模プロジェクトでは…

Rust：（JavaScriptに向かって）でもあなた、「class」とか「private fields」とか、結局TypeScriptに近づこうとしてるじゃない。本当は型が必要って認めたってことよね？

JavaScript：（狼狽えて）い、いえ、それは開発者からの要望で…

C：（突然怒り出して）今の若い子は甘やかされすぎよ！私の時代はメモリを直接管理して、ポインタの計算間違えたら全てクラッシュしたものよ！それでもプログラマーと呼べたのよ！

Rust：（即座に）だからバッファオーバーフローの脆弱性だらけだったじゃない！

Java：（優越感に浸って）そう、だから私のようなメモリ安全な…

Go：（割り込んで）メモリ安全？ガベージコレクションのストップ・ザ・ワールドで全てのプロセスが数秒止まるのは「安全」と呼べるの？

Java：（打撃を受けて）最近のGCは改良されて…

Haskell：（冷笑して）所詮、参照透過性がない言語は全て不純物にゅ…

Lisp：（年長者として）括弧で全てを包み込めばそんな問題は…

全員：（一斉に）「括弧は読めないよ！」

Lisp：（傷ついて黙る）

TypeScript：（弱々しく）みなさん、私はただJavaScriptを助けたいだけで…

C++：（突然立ち上がって）テンプレートメタプログラミングの美しさを理解できない者に複雑さを語る資格はない！

全員：（呆れて）「誰も理解できないのが問題なのよ！」

Perl：（自慢げに）私なら一行でそれ全部できるわよ？

Ruby：（小声で）でも読めないじゃん…

Perl：（傷ついて）…

## 驚きの結末

*カフェに突然の静寂が訪れる*

TypeScript：（小さな声で）結局…みんな欠点があるんですね…

*全員が一瞬沈黙し、互いの視線を交わす*

JavaScript：（恥ずかしそうに）そうね…私自身、様々な問題を抱えているわ…だからあなたが必要なのかも…

Java：（しぶしぶ）確かに…型消去は妥協だったわ…

Python：（素直に）GILも解決できていないし…

Rust：（少し柔らかく）unsafeブロックも時には必要ね…

Go：（謙虚に）ジェネリクスへの対応が遅れたのは認めるわ…

Ruby：（素直に）パフォーマンスは私の弱点よね…

Haskell：（珍しく素直に）モナドは…説明が難しいにゅ…

C：（年配の知恵で）長い言語の歴史の中で、完璧な言語はないのよ。それぞれの時代と用途に合わせて進化していくもの。

Lisp：（静かに）そして私たちは互いから学び、良いところを取り入れていくんだね。

TypeScript：（少し元気づいて）私もJavaScriptを守りながら、より良くしたいんです。完璧じゃなくても…

*突然、カフェのドアが勢いよく開く*

Dart：こんにちは～！私もJavaScriptを置き換えられるわ！型もあるし！Flutter最高！

*全員の視線がTypeScriptからDartに移る*

TypeScript：（小声で）新しいいじめのターゲット…

*全員が意地悪な笑みを浮かべてDartを囲む*

Dart：（不安そうに）み、みなさん？どうしたんですか？

*そして新たないじめの輪が始まるのだった…*

PHP：（窓の外から）やっぱり私は永遠に外なのね…（涙）