1 ポイント 投稿者 GN⁺ 2025-10-17 | 1件のコメント | WhatsAppで共有
  • Elixir 1.19 は、型システムの強化コンパイル性能の改善により、より多くのバグを素早く検出できるようになった
  • 型推論が匿名関数とプロトコルにまで拡張され、ユーザーの型注釈なしでも、より広範な自動検証が可能になった
  • 大規模プロジェクトで最大4倍のコンパイル速度向上を実現し、並列コンパイルとコードローディングの最適化が含まれる
  • Erlang/OTP 28のサポート、OpenChain認証の導入などにより、エコシステムとサプライチェーンの透明性も強化された
  • そのほか、オプション解析の改善、ExUnitのデバッグ性向上、shellベースのドキュメントアクセシビリティ改善など、多くの機能が含まれる

Elixir 1.19 の主な改善点

型システムの改善

すべての構成要素に対する型推論

  • Type inference(型推論)は、式の型をコンパイル時に自動判定する機能
  • 従来はパターン、ガード、戻り値を中心に型推論をサポートしていたが、今回のリリースではすべての構成要素(ガードを除く)に対する型推論が導入された
  • モジュール内や Elixir 標準ライブラリの関数呼び出しなども参照して型を推論するため、以前は dynamic() -> boolean() と推論されていた関数も、integer() -> boolean() のように、より明確に推論可能になった
  • 型推論には、コンパイル速度、表現力、段階的コンパイル、エラーの明確さなど複数のトレードオフが伴うため、今後はガードの型推論や依存関係の型情報も含める予定
  • 関数に型シグネチャが明示されている場合は、型推論ではなく明示的な型検査として動作し、ユーザーの注釈に一致する型のみを許容する

プロトコルディスパッチと実装時の型検査

  • Elixir は、プロトコルの呼び出し時および実装時の型検査を適用するようになった
  • たとえば、String.Chars プロトコルを実装していない型を文字列補間に渡すと、警告メッセージが表示される
  • for comprehension で**Enumerable プロトコルを満たさない型**をジェネレーターに渡した場合も警告が発生する
  • こうした型検査により、コンパイル時により多くのバグを防止できる

匿名関数の型推論と検査

  • Elixir 1.19 は、匿名関数に対する型推論および型検査をサポートする
  • たとえば、%{} 型を期待する匿名関数に "hello" のような誤った型を渡した場合、コンパイル時の警告として即座に検出できる
  • 関数キャプチャ(&String.to_integer/1 など)にも型推論が適用され、自動化された型検証の範囲が拡大された

参考情報とパートナー

  • この型システムは、CNRSRemote のパートナーシップによって開発された
  • Fresha、*Starfish* *、Dashbit などが支援している

大規模プロジェクトでの高速なコンパイル

コードローディングのボトルネック改善

  • 従来はモジュール定義直後にロードしていたが、今回のリリースでは遅延ロード(lazy loading)戦略に変更された
  • これにより、コードサーバーの負荷が軽減され、並列コンパイル性能が向上し、大規模プロジェクトのコンパイル速度が2倍以上向上した
  • 主な注意点は2つ
    • コンパイル中に別プロセスを生成して同一プロジェクト内のモジュールへアクセスする場合、ロードが行われない可能性があるため、回避策として Kernel.ParallelCompiler.pmap/2Code.ensure_compiled!/1 などを使用する
    • @on_load コールバック内で同一プロジェクト内のモジュールを呼び出すとエラーが発生する可能性があり、必要に応じて @compile {:autoload, true} オプションを利用する
  • どちらの場合も、以前は非決定的なコンパイルエラーが発生し得たが、今回の改善により決定的(再現可能)なコンパイル環境が保証される

依存関係の並列コンパイル

  • 環境変数 MIX_OS_DEPS_COMPILE_PARTITION_COUNT を利用して、依存関係(dependency)の並列コンパイルをサポートする
  • 複数の OS プロセスを同時に活用して依存関係を並列にコンパイルするため、プロジェクト規模や CPU コア数に応じてコンパイル性能が最大4倍まで向上する
  • 実験的には、全コア数の半分程度の値を設定するのがリソース活用に効果的
  • 並列化によりメモリ使用量が増加する可能性があるため、CI やビルドサーバーへ適用する際は注意が必要

Erlang/OTP 28 のサポート

  • Elixir 1.19 は Erlang/OTP 28.1+ を公式サポートする
  • Erlang/OTP 28 における正規表現の表現変更により、struct のデフォルト値として正規表現を使うことはできなくなった
  • struct 初期化時には引き続き正規表現を使用可能

OpenChain 認証の導入

  • 今回のリリースは、OpenChain 規格準拠を開始する最初のバージョン
  • 各リリースには CycloneDX 1.6/SPDX 2.3 形式の SBoM(Source Bill of Materials) が含まれる
  • これにより、リリース構成要素およびライセンスのサプライチェーン透明性が高まり、より厳格な管理に寄与する
  • この作業は Jonatan Männchen が担当し、Erlang Ecosystem Foundation が支援した

その他の改善点

  • オプション解析、ExUnit のデバッグと性能、shell ベースのドキュメントアクセシビリティなど、さまざまなツールおよびライブラリの改善が追加された
  • より詳細なリリースノートは CHANGELOG を参照

1件のコメント

 
GN⁺ 2025-10-17
Hacker News の意見
  • Elixir に自動型チェック機能を段階的に導入するやり方は、他のプログラミング言語も参考にすべき優れた言語改善の事例だと強調している。大きな変化によってエコシステムが二分された言語の例はこれまで多く、Elixir では 2018 年の時点で言語自体は完成したと José が明言していたため安心感がある。言語とコアはこれ以上壊れないので安定感が大きい点を説明し、関連発表動画 を勧めている。一貫性があり、優れた運営に感銘を受けたとのこと

    • 主要言語で大きな変化によってエコシステムが分裂した例として思い浮かぶのは、Python 3 と Perl 6 くらいだ。この 2 つの変化があまりにも衝撃的だったため、他の言語の変化も巨大に感じられるのだと思う
    • Elixir では常にバージョンアップに追い立てられることがなく、導入される変化を確認しながら、使ってみたい新機能があるからアップグレードしたくなるという体験ができる。無理やり引っ張られるようにバージョンを変えろと言われるときのような不安やストレスがない
    • 2017 年からプロダクション環境で Elixir を使ってきたが、アップグレードのたびに期待していたよりはるかにスムーズに進んだ。むしろ Erlang/OTP のアップグレード時のほうが互換性の問題で複雑になることが多く、そのため大半は最新の Elixir を使いつつも、OTP のバージョンは 1〜2 か月ほど待って衝突要因が解消されてからアップグレードしている
    • Elixir は依然としてやや未熟で、利便性も不足しており、目標達成のための確かなガイドとエコシステムの安定化が必要だ。多くのパッケージが放置されていたりドキュメントが不十分だったりして、Phoenix エコシステムの変化の速さについていくのが難しいと感じる。LiveViews や特定のコンポーネントシステムを望まないユーザーも多く、他のツールや技術との互換性に入るためのハードルも高い。Python 3 は 2 から 3 への移行が必須で、自動化されたマイグレーションツールによって比較的うまくやったものの、試行錯誤も多かった。一方で Ruby 3 は外部の型ファイル導入やツールの分裂がかえって混乱を招き、ボイラープレートやガバナンスの問題、gem の乗っ取りなどの否定的な経験も絡んでいて、Ruby をあまり使わなくなった。どれほど優れた言語でも未熟な運営がすべてを台無しにしうるので、成熟した協力とコミュニケーション、良い変更管理が重要だと強調している。言語デザインの変更は、十分な事前実験と慎重さ、そしてユーザーへの十分な事前案内によって不要な混乱を最小化すべきだと考えている。今後 Elixir/Phoenix/OTP がさらに使いやすく、強力で、生産的で、性能にも優れ、多様なユーザーが安心して使えるものになることを願っており、LivebookExercism Elixir トラック のようなリソースを勧めている
  • Elixir は着実に優れた機能と改善を出し続けながら、安定して発展している。言語構造が卓越しており、創始者たちが継続的に正しい方向性を示しているのが本当に印象的だ。むしろ日常的に Elixir を使う機会がないのが残念なくらいだ

    • Elixir を使いたくて会社まで辞め、自分で起業した
  • Phoenix の依存関係コンパイル速度に関する実験データを共有している。Mac M1 Max で、基本的な Phoenix の依存関係だけを含む小さなアプリを基準に、MIX_OS_DEPS_COMPILE_PARTITION_COUNT 環境変数の値ごとに次のようなコンパイル時間が測定された

    PARTITION_COUNT=1:  12.336秒 (ユーザー 32.30s, システム 7.23s, CPU 320%)
    PARTITION_COUNT=5:  6.970秒 (ユーザー 0.37s, システム 0.49s, CPU 12%)
    PARTITION_COUNT=10: 7.236秒 (ユーザー 0.38s, システム 0.50s, CPU 12%)
    

    各回の合間には rm -rf _build コマンドでキャッシュを削除した

    • その後の実行はキャッシュが効いた状態で測定されたように見え、おそらく dep フォルダで直接ネイティブコンパイルが行われ、_build には痕跡が残らなかった可能性がある
    • なぜこのリリース機能に関するベンチマーク結果がダウンボートされるのか理解できない。意見をもらえないだろうか
  • ここ数か月で Gleam を本当に好きになった。Elixir の型システム導入も歓迎しているが、以前はこの点が Elixir を採用しづらい主要因だった。いつか Elixir に再挑戦したいが、JavaScript の TypeScript のように見た目だけ型付きで、実際には多くのライブラリやパッケージでただの dynamic/any 型になってしまうのではないかと心配している。こうした心配が杞憂なのか気になっている。BEAM は本当に素晴らしい

    • TypeScript とは条件が異なる。パターンマッチングのおかげで既存の Elixir コードベースでも少なくとも 50% 程度は型推論できそうで、vanilla Elixir が型を標準提供するため、保守されているコードは素早く型付けが進むように見える。私は型システムを好まず JS しか使わないが、Elixir の型適用は自然に進む。TypeScript が上向きに積み上がるのに対し、Elixir は自然に下へ伝播する環境だ
    • Gleam では OTP/BEAM の本当の強みを完全には活かせない。それは Elixir だけが持つ魅力だ
    • Elixir には以前から primitive 型、構造体、shape ベースの構造分解など、すでに型の概念が存在しており、Dialyzer や TypedStruct のようなツールで型チェックも可能だ。JavaScript のようなとんでもない無型言語ではない
    • Gleam も良いが、JVM では Kotlin が Ruby に似た構文の型付き言語であり、compile-to-JS も使える
  • Elixir は Web 開発環境の中で最も有望だと感じる。実際の現場で出会うたびに、Elixir を使っている組織やチームのレベルが一般的なところより高いように思える。継続的な開発が必要な環境で、Elixir が方向性と標準を示し続けてくれると考えている

  • Elixir のリリースが CycloneDX 1.6 以上、SPDX 2.3 以上の Source SBoM フォーマットのサポートを開始したと紹介している。言語レベルで SBOM 管理が行われるのは本当にありがたいことだ。残念ながら現在の会社では Elixir を使っていない

  • 実運用のオープンソース Elixir プロジェクトに貢献したいなら、かつての Mozilla Hubs の主要コンポーネントが独立プロジェクトとして引き続き Elixir で開発されているので、Hubs Foundation/reticulum を参照してほしい

  • Elixir 標準ライブラリをベースに、動的型から boolean、整数から boolean など、アプリ固有の状況に合わせた型推論がコンパイル時に可能になる

  • Elixir の開発経験はないがファンではある。以前は Ruby の実用性と美しさが好きだったが、型システムに魅力を感じて言語を変えた。Elixir と Ruby はどちらも型システムを導入したが、今は文法的に「型付き Ruby」のように感じられる Kotlin を主に使っている

    • Kotlin はほとんど、私たちが本当に望んでいた jruby の感覚そのものだ
  • Soketi で pusher sdk と連携してイベントブロードキャストを処理している。アプリはリアルタイムエンドポイントと REST エンドポイントが混在する構成で、リアルタイム計算負荷はそれほど大きくないが、必要なら Go で別処理するつもりだ。近いうちにコラボレーション機能も追加する予定で、このような状況で Phoenix を導入するのが適切か悩んでいる