第6章で「パラダイムは置き換えではなく蓄積される」ことを見ました。その蓄積の必然的な帰結が、本章のテーマ—— 収斂(convergence)です。2010年代以降、かつてHaskellやMLという「専門家向け言語」にしかなかった機能が、 Java・Python・C#・JavaScriptへと次々に流れ込みました。言語たちは互いに似通い、もはや「純粋な命令型言語」も 「純粋な関数型言語」も主流からは姿を消しつつあります。この15年の大移動を、年表とコードで辿ります。

関数型の民主化

この潮流を一言で言えば「関数型の民主化」です。学術的・難解とされた関数型の道具——ラムダ式、 パターンマッチ、不変データ、代数的データ型——が、ふつうの開発者が毎日使う言語の標準機能になりました。 まずはその流入を時系列で見ましょう。

C# 3.0 — ラムダ式とLINQ

アンダース・ヘルスバーグ率いるチームが、Haskellに着想を得たラムダ式・LINQ・型推論(var)を一括導入。関数型機能の主流言語流入の先駆け。

C++11 — ラムダ式

C++がついにラムダ式 [](int x){ return x*2; } を獲得。

Java 8 — ラムダとStream API

「厳密にOOP」だったJavaが x -> x*2 とStreamを獲得。関数型へ踏み出す歴史的一歩。同年Swiftも登場。

Kotlin 1.0 — data classとnull安全

「Scalaの機能をJavaの速度で」を掲げ、data classとnullable型(T?)を標準装備。

Java/C# — レコードとswitch式

C# 9.0のrecord、Java 14のrecord(preview)。1行で不変データ型を定義。代数的データ型の系譜。

Python 3.10 — 構造的パターンマッチ

PEP 634でmatch文が追加。動的言語の代表格にも関数型由来のパターンマッチが到達。

Java 21 — パターンマッチ正式版

switchのパターンマッチング(JEP 441)が正式化。MLが1973年に確立した機能が、50年かけて主流へ。

ラムダ式 — 全言語に行き渡った関数値

「関数を値として扱う」というラムダ式は、もっとも広く伝播した関数型機能です。いまや書き方の違いこそあれ、 ほぼすべての主流言語が持っています。構文を並べると、収斂の様子が一目でわかります。

C# (2007)      x => x * 2
C++ (2011)     [](int x){ return x * 2; }
Java (2014)    x -> x * 2
Swift (2014)   { x in x * 2 }
Kotlin (2016)  { x -> x * 2 }
Python         lambda x: x * 2

パターンマッチ — 50年かけた旅

第4章で「関数型由来の強力な構文」として紹介したパターンマッチの伝播は、特に劇的です。 ML(1973)が確立した機能が、半世紀をかけて主流言語に行き渡りました。

graph LR
  ML["ML 1973\nパターンマッチ確立"]
  OCAML["OCaml 1996"]
  SCALA["Scala 2003"]
  FSHARP["F# 2005"]
  RUST["Rust 2015"]
  CSHARP["C# 2017"]
  PY["Python 2021"]
  JAVA["Java 2023"]
  ML --> OCAML
  OCAML --> SCALA
  OCAML --> FSHARP
  OCAML --> RUST
  FSHARP --> CSHARP
  CSHARP --> JAVA
  SCALA --> PY
  style ML fill:#8b5cf6,stroke:#6d28d9,color:#fff
  style PY fill:#14b8a6,stroke:#0d9488,color:#fff
  style JAVA fill:#f97316,stroke:#ea580c,color:#fff
パターンマッチの伝播。ML(1973)から関数型言語を経て、25〜50年かけてPython・Javaという主流言語に到達した

Python 3.10(2021)の match 文は、その到達点の一つです。動的型付けの代表格にすら、 構造で分岐するパターンマッチが入りました。

# Python 3.10 — 構造的パターンマッチ(PEP 634)
match command:
    case {"action": "move", "direction": d}:   # 辞書の構造でマッチ+束縛
        move(d)
    case {"action": "quit"}:
        quit()
    case _:                                     # ワイルドカード
        raise ValueError("unknown")

レコード型とnull安全 — 収斂の典型例

「1行で不変なデータ型を定義する」レコード型は、収斂の教科書的な例です。Kotlin・C#・Javaが、ほぼ同じ機能を 数年差で獲得しました。見比べると、もはや方言の違いに見えます。

Kotlin (2016)  data class Point(val x: Double, val y: Double)
C#     (2020)  public record Point(double X, double Y);
Java   (2021)  record Point(double x, double y) {}

null安全も同様です。「10億ドルの失敗」——nullを発明したトニー・ホーア自身の有名な後悔の弁——を、 型システムで防ぐ設計がKotlin・Swift・Rust・TypeScriptに広く採用されました。

Kotlin      str?.length ?: 0        // セーフコール + エルビス演算子
Swift       str?.count ?? 0
Rust        opt.map(|x| x+1).unwrap_or(0)   // Option<T>
TypeScript  obj?.prop ?? default    // オプショナルチェーン(TS 3.7, 2019)

なぜ言語は収斂するのか

これほど揃って似てくるのには理由があります。大きく三つです。

要因 内容 具体例
良いアイデアの伝播 優れた機能は言語の系譜を越えて拡散する ML→F#→C#→Java とパターンマッチが伝播
競争と開発者の期待 他言語にある機能が無いと選ばれない KotlinがAndroid公式に → Javaが追随
プラットフォームの同質化 設計者が先行する「ベストプラクティス」を意識的に収集 Swiftは「Rust/Haskell/Ruby/C#等から学んだ」

収斂の影 — feature creep

しかし、機能が増え続けることには代償があります。feature creep(機能の盛り込みすぎ)、すなわち言語の肥大化です。 象徴がC++で、後方互換を保ちながらC++11・14・17・20と機能を積み増した結果、 「同じチーム内ですら、使っている機能が違いすぎて会話が噛み合わない」とまで言われます。

この流れに抗ったのがGoです。ロブ・パイクらは「意図的に機能を削った言語」として設計し、 当初はジェネリクスすら持ちませんでした。「遅いプログラマ・遅いコンパイラ・肥大したバイナリのどれかを選ぶトレードオフがある」 という問題意識からの選択でした。

なぜ新言語はみなC系の見た目になるのか

機能(意味論)が収斂する一方、構文(見た目)はもっと露骨に収斂しています。2010年代以降に登場した 新言語は、ほぼ例外なくC系の中括弧+後置型注釈という見た目を採用しました。

Go         (2009)  func double(x int) int { return x * 2 }
TypeScript (2012)  const double = (x: number): number => x * 2;
Swift      (2014)  func double(_ x: Int) -> Int { return x * 2 }
Rust       (2015)  fn double(x: i32) -> i32 { x * 2 }
Kotlin     (2016)  fun double(x: Int): Int = x * 2

どれも中括弧 でブロックを表し、型注釈を後置x: Int のように名前の後)にしています。 この一致には三つの理由があります。

理由 説明
学習コストの最小化 世界で最も使われるC・Java・JavaScriptがC系。馴染んだ見た目なら移行が楽
エコシステムの継承 TypeScriptはJS、KotlinはJava、SwiftはObjC——既存資産と共存するため見た目を寄せた
型推論との相性 後置型注釈は、型推論で省略したときに自然に読める(let x = 1

まとめ — 似てきた言語たち

本章では、2010年代以降の「関数型の民主化」を追いました。ラムダ式・パターンマッチ・レコード・null安全が、 ML/Haskellという源流から15〜50年かけてJava・Python・C#へと流入しました。収斂の駆動力はアイデアの伝播・競争・ プラットフォーム同質化であり、その影にはfeature creep(C++の肥大化、Goさえ折れたジェネリクス)がありました。 そして構文面では新言語がこぞってC系+後置型注釈に寄り、差別化は意味論の層へと移ったのです。

では、ここまで収斂した先に、構文はこれからどこへ向かうのでしょうか。最終章では、AIが日常的にコードを書く時代に 構文の役割はどう変わるのか、Mojo・Zig・Gleamといった新言語は何を試みているのか、そして「最も熱い新言語は英語だ」という 挑発的な主張の真偽を検討します。

理解度チェック

問題 0 / 50%
Q1

2010年代以降のプログラミング言語の最大の潮流を一言で表すと、最も適切なものはどれですか?

キーボード: 1〜4 で選択、Enter で回答