The Rust Programming Language を読んだ

The Rust Programming Language 日本語版 を読み終えました。Rust 2018 Edition に該当します。

概要

以下のトピックについて学ぶ。

  • インストール
  • 基本概念 (宣言、if/for、関数など)
  • 所有権
  • 構造体、Enum
  • クレートやモジュールなどのコード分割
  • コレクション(VecHashMap)
  • エラー処理(Result)
  • 抽象度の高いもの: トレイト、ジェネリック型、ライフタイム
  • テスト
  • 関数型言語由来の機能: イテレータ、クロージャ
  • Cargo, crates.io
  • スマートポインタ: Box<T> Rc<T> RefCell<T>
  • 並行性: mpsc Mutex<T> Arc<T> Send Sync
  • オブジェクト指向のデザインパターン(ステートパターン)が必ずしも最善ではないことを示す
  • パターンマッチ
  • unsafe
  • マクロ
  • 付録: 予約語一覧、記号一覧、導出可能なトレイト一覧、Rust の開発の周辺

プロジェクトとしてそれまで学んだことを手を動かして学べるのは、2 章の数当てゲーム、12 章の grep のサブセットを書く CLI、20 章のマルチスレッド Web サーバの 3 つ。

この本の良さは、丁寧に skip する事柄は今は説明しないがこの章で説明する、ときちんと示しているところ。また、抽象的な説明 → 例という流れが難しい概念には必ず入っており、例を通して理解が進む構成になっています。

他のプログラミング言語の経験のない初心者にいきなり勧めるなら個人的には minigrep の 12 章まで、もしかしたら 7 章くらいまでの場合もあるかも。あと、丁寧なため分量が多く、物量的に厳しい人もいるかもと思いました。Reference 的に使っても良さそうです。

できるようになったこと/理解したこと

  • Rust のよさを答えられるようになった。書く速度と実際の実行速度と安定を全て両立する意味で、速度と安定を売りにしている。
  • フィールド初期化省略、構造体更新記法など便利なものが色々あるので不便に感じたら調べてみるとよい。
  • 構造体の種類が説明できる。
  • {:?} だけでなく {:#?} もある(pretty print)
  • matchif let はほぼ同義だが、 if let は網羅性がないことに注意。
  • パッケージ、クレート、モジュール、パスの違いが説明できる。
  • 相対パスか絶対パスどちらを使うかの判断基準が答えられる。
  • コンパイル時にサイズがわかっていることが重要。これはスタックに置くためで、この辺に Box<T> やトレイトオブジェクトが関わってくる
  • panic!Result の使い分けの基準が答えられる
  • Deref Drop トレイトの挙動について説明できる
  • 内部可変性パターンについて説明できる
  • RefCell の使い所の一つを説明できる
  • メモリ安全、には循環参照のようなメモリリークが含まれていて、弾けない
  • 状態と振る舞いを型としてコード化すると、Rust っぽいいいコードになる(OOP オブジェクト指向 の章)
  • パターンとしてありうるものをいくつか挙げられる
  • マクロの種類を説明できる

本を読んでいる途中気づいたこと

  • すでに git で管理されたディレクトリ内で cargo new すると .gitignore が生成されずにあわや target/ が commit されてしまいそうになる。毎回 .gitignore をコピペしていたが new の引数でなんとかならないもんかな
  • 参照外し型強制は、暗黙のうちに行われる他言語での型変換のような不都合が何か起きたりしないのだろうか?と心配になった
  • assert_eq! のような assert 系は右左どちらに Expected を書いてどちらに Result を書くべき?これはコード規約で縛るべきなんだろうか
  • 使われていない use を消すコマンドが欲しい。終わりに一括でしゅっと消したい
  • test module? tests module?複数系なのかどうなのかディレクトリ名にも関わるところで混乱していた
  • 14.3 で、add-one という名前のクレートがあったので、命名的に underscore 区切りだと思っていたから(確かどちらでもいいはずだけど)驚いた。英語の本家の方も確認しておきたい。
  • drop でネットワークなどを記述するときはプログラマが drop に責任を持つので、あるステートマシン的なものに対し drop を自動生成するみたいな方法ができると嬉しそう。(drop の中身を自動生成できないだろうか?)
  • 循環参照を検知することはできないだろうか?
  • ここGolang のドキュメントへのリンクがリダイレクトされる?本家を調べてみて違ってたら jp の方に PR 送ってもいいかもしれない
  • Cons の無限検知のところで、無限の検知はどうやるんだろう?調べたい。
  • 参照外し型強制の、参照外しは型が合うまで何回も行うのだろうか?回数上限はあるのだろうか?
  • dyn で怒られることが多く、dyn を調べておきたい。

今後やりたいこと

  • cargo update の挙動がいまいち分からなかったので理解したい。
  • test を書いてリファクタリングする構成の教材資料を作ってサークルでハンズオン試してみたい
  • unwind のスタックのエラー時の動きを理解したい。
  • 借用チェッカーの問題集で格付けチェック A か B かみたいな形式のがあったら楽しそう
  • ループ vs イテレータのパフォーマンス比較の検証記事とか出してみたいな。組み込みでの場合とかに意味があるので、組み込み Rust での検証がしたい。
  • あるものを Export したい時に、どこに pub をつけなきゃいけないか教えてくれる仕組みを作りたい
  • 依存関係のライセンス一覧を出してくれる仕組みを作りたい。バイナリにバンドルするとか必要なはずなので、その辺り調べて仕組みに取り入れられると良さそう。
  • document 全部読むをしておいたほうが良さそうなもの: Option prelude collect
  • RFC から所望の単語周辺の検索をかけるものが欲しい
  • バイナリサイズを CI で追跡する仕組みを作りたい。
  • C++でのスレッドの扱いを理論面から勉強したい
  • unsafe が依存に含まれているかチェックする CI
  • C コンパイラを Rust で書く。ある程度の分量の、まともなコードを書く体験を積みたい。

感想

この本は 2022/01/22 - 2022/02/09 にかけて、30 回以上に分けて合計 20 時間 44 分かけて読み終えました。(めちゃ回数分けているのは休憩をこまめに入れたから) M1 Mac を用いてサンプルコードを手元で動かしたのですが特に困ったことはなかったです。

日本語版ではなく本家を読みたかったが、読む速度を考えて日本語版を選択しました。翻訳してくださっている方々に感謝。

これまで私と Rust との関わりは、自分用に CLI ツールを書いたり、OSS を読んだりする程度でした。TRPL は 2019 年に少し読んで、4 章の所有権を読んで Rust が分かった気になり、以降、5 章の構造体からは読まずに必要になったらつまみ読みするくらいでした。

しかし今回、通しで読んでみると色々と発見があったり、ライブラリでよく見るあれはそういう意味だったのねと納得することもあって楽しかったです。TRPL を初手で読むのは私にはハードルが高かったのですが、いくつかライブラリを使ってみた後に読み返すと発見があり、ライブラリを使ってそれっぽいコードを書けるが初心者から脱した気になれない自分にはかなりいいタイミングで読めた気がします。

今後やりたいことにも書いたが、これからまともなコードを書いて一人前の rustacean になれるよう修練を積みたいです。