ローファイ日記

出てくるコード片、ぼくが書いたものは断りがない場合 MIT License としています http://udzura.mit-license.org/

型付きRubyでパーサを書く(後編)

今までのあらすじとして、ここまでで、Rubyでパーサを書き、めでたくRBSで型を付けました。

udzura.hatenablog.jp

udzura.hatenablog.jp

github.com

本エントリでは簡単にふりかえってみます。

大前提として、個人の感想で、皆様の今後の型ライフにほんのちょっと参考になればいいなというのはありますが、個人の日記の話です。

また、僕が誤解している内容もたくさんあると思うのでその際はご教示願います。

ふりかえりと感想

  • 型があると便利

とにかくこの一言に尽きます。以下はその内容の補足みたいなもの。

  • 型から設計を始められるのは体験がある

チーム開発で間違いが減ります!的なところもそうですが、個人的には 型から設計を開始できる ようになったのが大きいなと思っていて、今まで漠然とデータ構造を決めていたのがある程度きっちり決まるし、しかもそれを静的解析する仕組みが入る、というのは生産性に好影響かと。

  • 型から設計を始める選択肢を取れるように、型を始めると良さそう

例えば、Scala、Kotlin、Rust、Swift、Haskellのような一定以上リッチな型をサポートする言語の経験があった方がRBSでももっと捗るんではないか? と思いました。

個人的に今年はひたすらRustを書いていたためか、いざシグネチャを記述していく際もRustでコードを書くような感覚で行うことができました。

RBSを本格的にやっていく前提として上述の言語を経験して、型感覚を磨いておくのはいいかもしれません。

  • 型感覚って何?

型感覚、一体何者なのでしょうか。僕は今、 Result<Option<Rc<RefCell<AType>>>, Box<dyn Into<TheError>>> のような型定義にむしろ安心感を覚える人間になっていますが、そういうことではなさそうな気もします。ただ、RBSでもある程度複雑な型は既に表現できるようです。

  • 新しいRubyのコードスタイル

型を最初に決める設計もそうですが、型がいい感じに付くようにRuby側のコードを変えていく動きがどうしても生まれるように思います。

直近の問題としてあるのは、RBS自体の仕様も、TypeProfやsteepのような静的解析のツールも発展途上にあると思うので、ツールの現在の制限を回避するために多少冗長あるいは不自然な書き方が出てくるパターンがありそうだ - というところです。

前編 でもいくつかその手の回避を行っていたりしました。ただしこういうものは徐々に改善されていくものなので、まずはこうなって欲しいと思ったらフィードバックするのがいいと思います。

  • 「人が先、機械があと」が少しだけ変わりそうな気がする

一方で、例えば、無闇に戻り値の型を変えているようなコードであったり、同じ変数に別の型を押し込んでいるようなコードは減っていくと思います。また、ある程度 静的解析に優しい の書き方を意識する必要が出るかもしれません。型が入るとそういう動きはどうしても生まれそうに思います。

ただ、個人的には、静的解析に優しくなるタイプのコードの変更は、可読性や保守性の向上につながりやすい面もあるかと思いますので、必ずしもネガティブではありません*1

要はバランス、みたいになりそうですが、Rubyを書くときのマインドがどうしても少し変わると思います*2

  • エディタなどエコシステムの発展に期待したい

少なくとも、簡易的にEmacsの各種モードやsteepのLanguage Serverを利用しただけでも、かなりの生産性の向上を感じました。

ただ、実際のコードとシグネチャが分かれているという仕様は難しところもあり、両方のファイルを編集しないといけないのは多少手間取ります。そこは、型解析機やエディタが上手に連携してくれたらだいぶ体験が違いそうです。例えばVSCodeRBSを直接いじるような拡張もあったような...*3

ドキュメント面や情報量も、まずはそもそも英語も日本語も少ないというのが正直なところだと思うので、たとえば るりまでのRBS解説ページの追加 なども検討されていますが、日本語でもいろいろアウトプットしていくといいのだろうと思います。

  • Rubyを使いたくなる範囲が結果的に広がりそう

今回は言語のパーサというテーマを選んでいますが、正直、言語実装のレベルで複雑なソフトウェアを書くとき、型付けの支援が得られるというのは 安心感 が違います。

Webもある意味でそうですが、Rubyはどうしてもスクリプト言語的な用途というか、日々の仕事の自動化やちょっとしたテキスト処理なんかに使われがちなのかもしれません。そして、言語自体の実装や複雑なシステムソフトウェアのようなものを書く際はC++JVM言語、Go、Rust、何よりC... のような選択肢が取られがちな印象があります。実際僕もある程度以上複雑なソフトウェアであればRustを第一の言語候補にすると思います。

ですがRBSに触れて、その印象がまた変わってきました。 型が助けてくれるんならもうちょっと複雑なやつもいけるんちゃう? みたいな気持ちになっています。 YJIT で速度面もさらに改善されるし、3.0以降の変更の結果はRubyの適用範囲拡大を後押しする結果につながりそうに思います。


取り留めもなく書いてきましたが、僕が言いたいことは 型を決めると気持ちいい! ということです。みなさんも型シグネチャ書いていきましょ〜う。

最後にRBSやsteepを使うにあたり参考にしたサイトなどを残しておきます。

RBSとsteepのREADME

github.com

github.com

むしろ、ほぼこれらの情報だけで書いたので遠回りしすぎたような...。

steepのsmoke test cases

github.com

記事など

pocke.hatenablog.com

zenn.dev

あと、 pockeさんからRBSの文法などについてのドキュメントを教えていただきました。BNFもありますね... ちゃんと読みます...。

github.com

*1:これもrustcさんやclippyさんに教え込まれているからかもしれない。

*2:Rubyの文法は「人が先、機械があと」みたいなことを昔Matzが言っていた記憶があるんですが、人も機械もハッピーになりましょう。

*3:記憶違いかも