「Rust の練習帳」で Rust に入門してみたので、その感想です。
Rust を学び始めた背景
普段 Go 言語をよく使っていますが、新しめの言語を学びたいというモチベーションと、一定の層に愛されている言語の魅力が何なのかを知りたいという理由で、Rust を学び始めました。 Rust の入門書として「Rust の練習帳」を手に取り、ゼロから学習を進めてみました。
ちなみにこの本は、echo, cat, head などの 13 個のシェルコマンドを Rust で簡易実装しながら、Rust を学ぶ本です。
自分のコードはこちら:https://github.com/Fukkatsuso/rust-practice-book
Rust で最初に戸惑ったこと
所有権と可変性
Rust には「所有権」という概念があり、これがメモリ管理の基礎となっています。 また、変数がデフォルトで不変(イミュータブル)であることも特徴的です。
個人的には、なるべく変数はイミュータブルな方が認知的に楽なので好きです。
ただ、Rust に入門したての頃は、「所有権」と「可変性」の区別が自分の中で曖昧になっていました。
mut
キーワードをつけないと変数を変更できないことはすぐに理解できましたが、&mut
で可変参照を渡す際の挙動をイメージするのはなかなか難しかったです。
Rust のコードをスムーズに書くためには、所有権の基本的なルールを理解することが重要だと思いました。 実際、5 章あたりまで読み進めた段階で、所有権の理解が曖昧なままでは厳しいと感じ、公式ドキュメントのいわゆる the book を参照して理解を深めました。
Result 型とエラーハンドリング
Go ではエラーを返す場合、(T, error)
のように複数の戻り値を返すのが一般的です。
Rust では Result<T, E>
でエラーを包んで返しますが、その扱いに最初はしっくりきませんでした。
特に、Result
から値を取り出すときの unwrap()
と ?
の使い分けが直感的に分かりづらかったです。
unwrap()
は値を取り出し、エラーだった場合は panic してプログラムがクラッシュする?
は値を取り出すが、エラーだった場合はエラーを呼び出し元に伝搬させる
使い分け方はこんな感じだと理解しています。
- 「ここでエラーが発生することはありえない」と確信できる場合に
unwrap()
を使う Result
がエラーを返すかもしれない場合は?
を使う
また、Go では if err != nil {}
という手続き的な書き方でエラーハンドリングするのが一般的です。
Rust の場合、Result
型に対して match
を使う方法もありますが、unwrap()
や ?
を使って処理するスタイルにはかなり文化の違いを感じました。
メソッドチェーンと型の混在
Rust では関数型言語のようにメソッドチェーンを活用することで、処理を簡潔に記述できます。
しかし、Result
や Option
型が混ざると、扱いが難しくなると感じました。
たとえば、Option<Result<T, E>>
を Result<Option<T>, E>
に変換する transpose()
は全く見たことがないメソッドでした。
map()
を適用してからの map_err()
や ok_or()
, and_then()
など、型や条件によって様々なメソッドをチェーンさせていく書き方は、読めばある程度わかりますが自力で書くのは今でも難しいです。
これらは Rust の練習帳ではサラッと書かれていましたが、Rust 初学者にとっては初めて見る書き方だったので混乱しました。
Go ではこのようなメソッドチェーンを使うことがほぼないため、不慣れな状態で Rust のコードを書くのはかなりエネルギーが必要だなと思います。 一方で、コンパイルが通れば(ある程度は)安全に動作することが保証される点は魅力的です。
この本を読んだ感想
この本そのものが難しいというよりも、Rust を初見でいきなり書き始めるのはなかなか大変だと感じました。 基礎からじっくり学ぶのではなく、実際にコードを書きながら必要な知識を身につけていくスタイルの人には、この本は適していると思います。 言語仕様や概念については、the book を辞書的に読むことで補完するのが良さそうです。
そして、Rust の文法だけでなく、CLI ツールの実装方法について学べたのも収穫でした。
特に 8 章の cut コマンドにおける parse_pos
関数の実装は、CLI の引数に様々なパターンの文字列が渡される場合に、どのように解釈すればよいかを学べました。
CLI ツールの作成に慣れていない人であれば、まず自分なりに考えて実装し、模範解答と比較することで、「なるほど」と感じる部分が多いと思います。
また、全体を通して、CLI の出力処理のコードがエレガントに書かれており、とても参考になりました。
まとめ
Rust を学ぶ上で、最初に所有権を理解することが大切だと感じました。
また、the book などの公式ドキュメントを活用しながら、Result
型のエラーハンドリングや、Rust ならではのメソッドチェーンの書き方に慣れることもポイントだと思います。
Go 経験者として Rust に入門した感想としては、Rust は学習コストが高い一方、その分得られる安全性は魅力です。 メソッドチェーンをうまく使えば、簡潔かつエレガントなコードを書ける点も印象的でした。
ただし、「Rust の練習帳」では並行処理などのトピックが扱われておらず、読了後も Rust の概念についてわからないことが多く残っています。 Rust の良さをより深く理解するために、the book や他の書籍を活用しながら、並行処理など未学習のトピックを学びつつ、実用的なコードを書いていくことで学習を継続していきたいと考えています。