Elixir v1.20 リリースノート / 新機能
Elixir v1.20 は、言語を段階的型付け言語へと変貌させます。主なポイントは、Elixir コンパイラが型推論を実行し、開発者が既存のコードに型注釈を追加することなく、実行時に失敗することが保証される「検証済みバグ(verified bugs)」—つまり型違反—をすべてのプログラムでチェックできるようになったことです。
集合論的型システム
Elixir の新しい型システムは、健全で段階的、かつ開発者に優しいように設計されています。集合論的型を利用しており、これは型が和集合、積集合、否定といった基本的な集合演算を用いて構成されることを意味します。
dynamic() 型とバグ検出
多くの段階的型付けシステムで見られる any() 型のように、型チェックを無効化してしまうものとは異なり、Elixir の dynamic() 型は型情報を保持します。これには、互換性と**絞り込み(narrowing)**という2つの重要な特性があります。
- 互換性: 型違反は、提供された型と受け入れられる型が完全に互いに素(disjoint)である場合にのみ報告されます。もし少しでも重なり(積集合)があれば、コードは互換性があるとみなされます。これにより、動的なコードを扱う際に静的型付けシステムでよく発生する誤検知(false positives)の量を防ぐことができます。
- 絞り込み (Narrowing): 型システムは、変数が使用されるにつれてその型を洗練させることができます。例えば、変数がマップのキーアクセス (
data.a) として使用される場合、コンパイラはdataの型を、キー:aを含むマップへと絞り込みます。もしその後のコードで同じ変数を整数として使用しようとすると、コンパイラは、絞り込まれた型(マップ)が期待される型(整数)と互いに素であるため、型違反をフラグとして報告します。
ガード節と節における型推論
Elixir v1.20 は、いくつかのコアな言語構造において型絞り込みと型チェックを実装しています。
ガード節
コンパイラは、ガード節から型を推論できるようになりました。例えば、when is_list(x) は x がリストであることを推論し、when not is_map_key(x, :foo) は x が具体的にキー :foo を含まないマップであることを推論します。また、データ構造のサイズも追跡します。when tuple_size(x) < 3 のようなガードは、タプルが最大2つの要素を持つことをコンパイラに認識させ、無効な elem/1 呼び出しを防ぎます。
Case 文と条件分岐
型情報は各節(clause)を渡って洗練されます。case 文において、最初の節が nil に一致する場合、コンパイラはそれ以降のすべての節において、その変数がもはや nil でありえないことを認識します。この絞り込みにより、コンパイラは冗長な節を見つけ出し、既存のコードベースにおけるデッドコードを特定することができます。
コンパイル性能とツール
Elixir v1.20 は、特にマルチコアマシンにおけるコンパイル速度の向上を導入しています。合成ベンチマークによると、Elixir のビルドツールは現在、BEAM 言語の中で最も高速です。
さらに、新しいコンパイラオプション :module_definition により、開発者はモジュール定義を :interpreted に設定できます (mix.exs 内の elixirc_options: [module_definition: :interpreted] を使用)。これにより、ディスクに書き込まれる最終的な .beam ファイルに影響を与えることなく、大規模プロジェクトでのコンパイル時間を短縮できます。
将来のロードマップ
While v1.20 は注釈なしでの型推論を提供しますが、Elixir チームは、明示的な型シグネチャの研究と開発を継続しています。これらは、以下の基準が満たされた後にのみ導入される予定です。
v1.20 の型システムのパフォーマンスが検証されること。
再帰的型の効率的な実装。
パラメータ型(parametric types)の効率的な実装。
列挙可能なものとしてマップのキーと値のペアを走査する効率的な実装。
コミュニティの視点
このリリースに対するコミュニティのフィードバックバックは、様々ですが、概ね良好です。一部の開発者は、アップデートによって提供される「無料」のバグ検出機能に称賛を送っており、あるユーザーは次のように述べています。
"It's very nice updating Elixir, having no breaking changes across my many projects and it then the compiler just finds bugs for free."
逆に、一部の批評家は、最初から型付けされていない言語に型を追加することは、Gleam や Rust のような言語に比べて本質的に効果が低いと主張しています。また、Dialyzer の「success typing」との比較や、段階的型付けシステムがプログラムの漸近的パフォーマンスに影響を与えるかどうかを疑問視する声もあります。