Rustコトハジメ

プログラミング言語Rustに関する情報をお届けします。

エディタ開発で5400行もRustを書いてしまったおれが思うRustの良さ

VSCode形式のスニペットを読み、それをTrie木で管理し、挿入モードで文字が入力された時に候補となるスニペットを探し、それを表示し、バッファに挿入するということが一通り出来るようになりました。

実装はやや難解な点もあり、かなり疲弊したので開発はしばらくお休みしたいと思いますが、エディタアスペなのでどうせまた明日も明後日もフルスロットルで開発してしまうでしょう・・・。本当は競プロ勉強に戻りたいんですが。

f:id:akiradeveloper529:20190401164222g:plain

気づいたらコード量が5400行になっていました。一応、小規模なソフトウェアは卒業したと言ってもよいでしょうから、ここで、Rustで中規模なソフトウェアを作った私が思うRustの良さについて経験をベースにして語ろうと思います。

f:id:akiradeveloper529:20190401164649p:plain

ソースコードを読みたい人はこちら。今ならまだ全部読めるでしょう。

GitHub - akiradeveloper/ijk: A real editor for real programmers

さて。

所有権システムと型に守られてとても安心

Rustの所有権システムは初心者にとっては理解しづらいものの一つで、敵のように見えるかも知れませんし、実際おれにとってもそうでしたが、ソフトウェアが大きくなっていくにつれて、コンパイラが友達であることがわかってきました。

ある時に可変参照を持ってるということは、それは絶対に自分が独占していて、他に不変参照を持っている人が絶対にいません。また、ある時に不変参照を持っていたら、それは間違いなく不変で、まるで不変なデータのように扱うことが出来ます。これが、プログラムのロジックを考えることを容易にします。これは関数型がある種のロジックを書くことを容易にするのと同じです。

Rustでコードを書く時は、コンパイル時にチェックされる領域を出来るだけ増やすことが良いと思います。その上に、Rc<RefCell<T>>のような層を止むを得なく被せていくことをおすすめします。こうすることで、安心出来る部分が多くなるからです。これは、Haskellで、出来るだけ純粋な部品を作っていくことが望ましいのと似ているかも知れません。

enumやパターンマッチによるプログラミングは、「プログラミングとはデータ型を変換していくことである」を実行することを容易にします。これももちろん、ロジックをシンプルに書くことを容易にします。

所有権システムは、データの配置について設計を強制する

所有権システムを活用するためには、「どのデータをどこに置くか」「誰がそいつの所有権を管理するか」をしっかり考える必要があります。これは、プログラム設計でもっとも大事なところです。他の言語でも、データの置き場所がおかしいと違和感を感じることがあると思いますが、Rustでは、それが極端になります。場合によっては書けないコードがあるからです。

データを正しい場所に置くことによって、データの依存関係が見通しやすくなりますし、結果としてロジックも理解しやすくなります。

デメテルの法則の価値が低くなる

長いメソッドチェーンをやめなさいというというオブジェクト指向の法則がありますが、Rustでは、メソッドチェーンをしていった先を変更する時には、その始点も&mut参照をとれないといけません。そのチェーンはすべてそうです。従って、その途中で他の人がデータを変更しないということが保証されます。比喩的な表現になりますが、チェーンが一本の棒のようにがっちりと固められているという印象を受けます。

もちろん、メソッドをチェーンを短くすることは、見えてしまうものを減らすという意味では依然として有益ですが、そこまで神経質になる必要はないのかなと思いました。静的型であることも助けて、気になった時にいつでも安全にリファクタリング出来ますから。経験的には、気にせずメソッドチェーンをしまくっても、他の言語ほど問題に感じることはないです。

関数の型を書くことを強制する仕様は役に立つことが多い

Rustは、関数を書く時にその型を全部書く必要があります。これは、「それ自体がドキュメントになる」という考えのもとわざと型推論を省いてるという主張だったと思います。これは賛否両論があると思います。実際に開発をしていると、鬱陶しいと思うことも多いですが、型が書いてあることであとで読んだ時に理解を助けることが多いです。

また、関数の型に&mutなどの所有権や可変性に関する情報が含まれていることで、それが一体何をするものなのか明白になります。これは、使った時にコンパイラの保証を得るということもありますが、ライブラリのソースコードやドキュメントを理解する時にも役立ちます。

エコシステムが優秀

Rustでは、良く設計された高品質なライブラリがすぐに見つかります。これは、Rustが他の言語から多くの概念を引き継いでいる後発の言語ということもあります。これによって、他の言語である優れたライブラリをそのデザインを参考にして持ってくるということがものすごい勢いで行われています。特に、「ScalaにあるものはRustにもある」感はわりと強いです。

また、cargoはとても使いやすいです。

モジュールシステムが使いやすい

あまりモジュールシステムに詳しくないので、Rustのそれが他の言語でいうとどれに似ているのかわかりませんが、Pythonでしょうか。

開発していて思うことは、新しいモジュールを作って開発を進めていく時に、あまり真剣に考えずにとりあえずやってしまっても、あとからそれほど後悔しないことが多いです。そのモジュールが肥大してしまったらディレクトリを作ってmod.rsを作ってファイルを分割すればいいですし、最初からディレクトリを作るかどうかなど迷う必要があまりないです。

コンパイルが速い

5400行書いて、それなりに静的ディスパッチも使ってるにしてはコンパイルが速いと感じます。私はここ数年はScalaを書いていましたが、それに比べるとだいぶ速いという印象を受けます。JVMを起動する時のもっさりとした感じがないのも良いです。あれはかなりイラっとしますから。