1 ポイント 投稿者 GN⁺ 3 시간 전 | 1件のコメント | WhatsAppで共有
  • 型推論と段階的(gradually)型検査がすべての Elixir プログラムに適用され、型アノテーションがなくても、デッドコードや実行時に必ず失敗する検証済みバグを見つけられる
  • dynamic() 型は、何でも許容する any() とは異なり、実行時に取り得る型の範囲を追跡し、許容される型とまったく重ならない場合にのみ違反を報告する
  • dynamic(integer() or binary()) の値は、数値演算や文字列関数のように一部の可能性が重なる呼び出しでは違反にならないが、Map.fetch! のように map だけを受け取る呼び出しでは違反になる
  • dynamic() は使い方に応じて絞り込まれ、data.a + data.b のようなコードでは、data%{..., a: number(), b: number()} 形式の map として精緻化する
  • guard では 和集合・積集合・否定 を推論し、is_listis_integeris_map_keynot is_map_keytuple_size のような条件を型情報として活用する
  • case と条件分岐は、先行する節の情報を次の節に反映し、先に nil を処理したあと残りの値を binary() に絞り込む、といった型検査を行う
  • 標準ライブラリの tuple・map 関連の複数の関数に型が追加され、既存コードベースで重複した節やデッドコードを見つける助けになる
  • “If T: Benchmark for Type Narrowing” では 13 カテゴリ中 12 カテゴリを通過し、一般的な Elixir コードで高精度な型情報を復元できることを示した
  • v1.20 はマルチコア環境のアプリケーションでコンパイル時間を再び改善し、合成ベンチマークでは Elixir のビルドツールが BEAM 言語の中で最速の結果を示した
  • 新しいコンパイラオプション :module_definition により、module 定義の実行方式をデフォルトの :compiled または :interpreted から選べるようになり、mix.exselixirc_options: [module_definition: :interpreted] で有効化できる
  • :module_definition オプションは、ディスクに書き込まれる .beam ファイルには影響せず、defmodule 内部の実行方式だけを変更するもので、大規模プロジェクトのコンパイル時間改善に役立つ可能性がある
  • 集合論的型を活用する新しい型シグネチャは、v1.20 の型システム性能、再帰型、パラメータ化型、map の key-value 走査に関する研究が満たされたあと、typed struct 定義とあわせて議論される予定である

1件のコメント

 
GN⁺ 3 시간 전
Hacker Newsの反応
  • 個人的な経験かもしれないが、最初から型があった言語でない限り、真の静的型付き言語ほどうまく機能しない気がする

    • 同意するが、別の見方もある: “Why are gradual static types so great?” https://www.benkuhn.net/gradual/
    • 一方で TypeScript は、型のない言語で人々がやってきたありとあらゆる奇妙なパターンをサポートしなければならないので、私が最も気に入っている型システムになっている
  • Elixir のプロ開発者として10年ほど働いてきて、型の導入を長く待ち望んでいた。今回その第一歩が実際に入ったのは本当にうれしい
    ただ、v1.20 に入った現状が、仕様なしの Dialyzer と比べてどうなのか知りたい。Dialyzer の**成功型(success typing)**アプローチは、「失敗しうる引数の組み合わせがあれば警告」ではなく、「動作する引数の組み合わせが1つでもあれば警告しない」に近いと理解しているが、Elixir がここでやっていることも似たものだと思っていたし、Dialyzer はあまり有用だと感じなかった

    • まだ運用中の10年物のElixir コードベースから何が見つかるのか気になる
  • Elixir の段階的型システムに関する記事は HN で何度か見たが、詳しく追ってはいなかった。この段階的型システムが、型なしコードと比べてプログラムの漸近的計算量を変えうるのか知っている人がいるか気になる
    私の知る限り、Racket のような大半の段階的型システムは、プログラムを漸近的に遅くしうるし、例外も一部ある [1]
    [1] https://doi.org/10.1145/3314221.3314627

    • Elixir の段階的型システムは、プログラムの漸近的計算量を変えない。設計上、他の段階的型システムで遅くなる原因である静的/動的境界でのランタイムキャストを明示的に排除している
      ほとんどの段階的型システムは、型付きコードと型なしコードの境界を値がまたぐときに強制を挿入する。たとえばリストの全要素を検査したり、値を型プロキシで包んだりする。しかし Elixir チームは、そうしたランタイム検査なしで健全性を得るためにstrong arrowsの結果を発表しており、コンパイラが出力するバイトコードは型なしコードと意味的に同一である
  • 皮肉なことに、批判者たちは型が必要だと言い、Elixir ファンは型は不要で Elixir はなぜか魔法のようだから型関連のバグは起きないと言っていたのに、いま型を入れたらバグを見つけてくれている。バグ防止に必要ないのではなかったのか? それでも良い変化だ。以前 Elixir をかなり使って楽しんでいたが、型の不在には同意しづらかった

    • これはGoomba fallacy
      https://en.wiktionary.org/wiki/Goomba_fallacy
    • Elixir をそこまで深く追っていたわけではないが、Erlang 側の議論で見たものは少し違っていた。どうせ失敗は優雅に処理しなければならないのだから、型エラーもすでに備えるべき障害回復の仕組みで処理すればよい、という流れだった
      その観点には同意しないが、「$LANGUAGE は魔法」よりははるかに擁護可能な主張だ
    • そういう主張を一度も見たことがないと断言はできないが、記憶にはないし、あったとしてもごく少数だったはずだ。実際の反対論はおおむね「型は良いがコストがあり、そのコストが常に十分な見返りになるとは限らない」に近い
      集合論的型理論が発展する前は、そうした立場にも妥当性があった可能性がある
    • JavaScript/TypeScript や Python でも同じことがあった。時には、人は信じたいように信じるものだと受け流すしかない
    • 生命のサイクルだ。動的型付け言語にはファンがつき、別の人たちは静的型があればはるかに有用になると正しく指摘する。ファンはそれを個人攻撃のように受け取り、静的型は不要だと言う。理由は「どうせ役に立たない」「言語の精神に反する」「ただのスクリプト言語だ」「デバッガを使えばよい」「静的型は生産性を損なう」などさまざまだ
      そして結局、静的型が追加される。Python、JavaScript、Ruby で起きたし、ほかにもあるだろう
  • Elixir を更新しても複数のプロジェクトで破壊的変更がなく、しかもコンパイラが無料でバグを見つけてくれるのは本当に素晴らしい。すっかり慣れてしまった

  • これを見ると本当にうれしい。これで「素晴らしい言語」にかなり近づいていて、私にとって Elixir は第一候補だ
    すでに使いやすいのに、優れた機能を安定的かつ安全に追加し続けている他の言語があるなら教えてほしい。Go をある程度極めたあと、高度な C# を学ぶ方向に移ったが、Go は良い機能追加が止まった感じがしていた

  • この1か月、Elixir exercism.io トラックを進めてみた https://exercism.org/tracks/elixir
    本当に素晴らしい

  • ああ、また始まった。また1年かけて Elixir を学び直すことになりそう
    Elixir のあらゆる点が好きだけど、どの言語よりも Elixir は自分自身を疑わせてくる。自分の脳は関数型に向いていない気がするけれど、この変化のせいでまた挑戦してみたくなる
    残念なのは、エコシステムが初心者に優しいとは言い難く、質問に答えるときにたいていすでにその言語をよく知っている前提になっていることが多い点だ

    • https://pragprog.com/titles/lhelph/functional-web-developmen...
      タイトルにだまされないように。この本の前半はただの Elixir だ
      この8年間、Elixir に再び慣れようとするたびにこの本を使ってきたが、毎回うまくいった。最後まで読んだことはない
      こういうチュートリアルプロジェクト形式のプログラミング本が良い本かどうかを見る基準のひとつは、何度も読み始めても最後まで行かなくてよく、中ほどまでで自分の仕事に取りかかれる道具がもう手に入るかどうかだ
    • 大学の「プログラミングパラダイム概論」みたいな授業で初めて Haskell を触ったとき、これを本当に痛感した。その時点ですでに何年もプログラミングをしていたのに、長いあいだ基本だと思っていたことをやり切るのに、あそこまで無力になり得るなんて信じられなかった
      でも、脳が向いていないというより、命令型言語で積み上げた経験値と、純粋関数型スタイルではまた初心者として始まることとの対比なんだと思う
      だんだん良くなっていくはず。関数型プログラミングがしっくりきたきっかけは、自分がゆったりスペースを入れた Bash の「ワンライナー」っぽいコードを組み合わせるのがどれほど好きかに気づいたときだった。データがある形で始まったら、コマンドで吐き出し、欲しい形に近づく段階を考えて次のコマンドにパイプし、また眺める。それを続けていくと、最後にはたいてい変更されないデータ変換の連なりが残る
      シェルでこれが心地よい理由のひとつは、毎日ファイルシステムをうろつきながらコマンドの語彙を蓄えているからだ。Unix 系環境で馴染みのある「関数」ライブラリは、何年もかけてかなり大きくなっている。純粋関数型プログラミング環境でも同じことをしなければならないが、語彙を覚えるのに少し余計な労力がかかる。よく使う「コマンド」は grep、cat、sort ではなく map、fold、zip のような関数になる
      でも本質は本当に同じで、パイプラインを組む魅力も両方にまったく同じように当てはまる。少しずつ作れるし、それぞれのパズルでは前の段階は忘れて、目の前のデータを次にどう変換するかだけを考えればいい。この低いコンテキスト依存性が新鮮で心地いい
      ぜひ試して楽しんでほしい。何かができない状態を楽しめるようになったとき、ようやく本当に上達する
    • Rust を少しかじっているか気になる。自分も関数型言語の経験は多くないけれど、Gleam は Rust っぽい部分のおかげで馴染みやすく感じられて、構文より概念に集中できた
      もちろん数回の午後を使った程度だけど、もう一度関数型言語に自分の脳を慣らすなら、その親しみやすさゆえに Gleam を選ぶと思う
    • ElixirForum で質問してみることを勧める。本当に敵対的な反応は見たことがない
      たまに曖昧すぎて関心を持たれないとか、「宿題を代わりにやってくれ」臭がして無視される投稿はある
      でも本物の好奇心がこもった投稿なら、自分が見る限りどれも返答をもらっている
    • こういう言い方はいつも混乱する。状態まみれのオブジェクト指向プログラムのほうが、自分にはよほど推論しづらい
  • すばらしい。1.20 では、うちの大きな umbrella アプリ のコンパイルがかなり速くなったように見える

  • Gleam と比べてどうなのか気になる。あるいは、これでなぜ Gleam ではなく Elixir を使うべきなのだろう? Phoenix、とりわけ LiveView が Elixir の大きな魅力ではありそう

    • Rust が好きか、Erlang が好きかの違いだ。Gleam を使うのは Rust を使っている感じで、Elixir を使うのは Erlang を使っている感じだ
      Gleam OTP の現状は知らないが、最後に見たときは良くなかった
      どちらでもよくて型だけが重要なら Gleam を使えばいい。でも、それならただ Rust を使えばいいのでは?
    • Gleam のウェブサイトに 比較資料 がそのままある
    • Gleam にはマクロがなく、Phoenix や Ecto のような多くの Elixir ライブラリは マクロ をとても効果的に使っている
      たとえば Gleam では JSON のデコード/エンコードが冗長になりがちだ。Rust なら serde を derive すればいいし、Elixir なら関数呼び出しひとつで済む
      Elixir にはより成熟したエコシステムがある。たとえば Gleam で Phoenix やほかの Gleam フレームワークを使うことはできるが、体験は同じではない
      Gleam が Elixir より魅力的に見える大きな理由は型で、Elixir はいまその差を縮めつつある。さらに JavaScript にコンパイルできる点もあるが、Elixir では Hologram が似たようなことをしている
      個人的には Gleam の型システムと Rust ライクな構文のほうが好きだが、現時点では自分のすべての Web 開発プロジェクト にとって Elixir のほうがより良い選択だと感じる
    • 実質的には Phoenix と Ecto のためだ