Effective Rust
2025年1月26日読了
Credit
David Drysdale. (2024). Effective Rust: 35 Specific Ways to Improve Your Rust Code. O’Reilly Media, Inc. 中田秀基訳. (2024). Effective Rust ―Rustコードを改善し、エコシステムを最大限に活用するための35項目. オライリー・ジャパン.
Summary
Rustの機能を理解してRustらしいコードを書くための手引書。基本的にはRustの機能を解説する。
Note
- 関数シグネチャだけでは表せない制約にはマーカートレイトを用いる。プログラマに対する暗黙の了解となるが。ある実装がされているだろうことを期待できる。
- ErrorはDebugとDisplayを実装すれば作れる。StringをErrorとするのはアンチパターンらしいので、ラップするなり自作するなりした方が良いか。enumをErrorにできる。
as
よりfrom
/into
を使う。- 複雑な型にはビルダを作る。
self/Self
か&mut self/&mut Self
かは利用者の需要を見て判断する。 - 「驚き最小の原則」なんてものがあるのか。加算オペレータと負数オペレータを実装しているならば減算オペレータも実装すべき。
Copy
トレイトを実装板としてもclone()
呼び出しにはコストがかかる(そらそうか)。ので、ビット単位でのコピーが有効的ならCopy
トレイトを実装してコピーする。Drop
トレイトを実装してデストラクタを実装できる。なぜDrop::drop()
は引数がself
ではなく&mut self
なのか?- ジェネリクスはC++のテンプレートのようなものなので、使えば使うほどコードが生成されることになる。
- トレイトオブジェクトはC++同様vtableのルックアップを行うのでジェネリクスよりわずかに遅い。また、トレイトオブジェクトは1種類のvtableしか持たないので、例えばAがBを実装していても、AのトレイトオブジェクトをBのトレイトオブジェクトとして見なすことはできない。
- トレイト境界はトレイトオブジェクトには使えない。同じことをするには新しくトレイトを定義すれば良いが、組み合わせの数が爆発しうる。
- 生存期間省略ルール:
- 参照の入力が1個、参照の出力が1個:出力は入力と同じか短い生存期間を持つ。
- 参照の入力が複数個、参照の出力が0個:すべての入力が異なる生存期間を持つと仮定される。
- 参照の入力が
&self
を含む複数個、参照の出力が複数個:出力は&self
と同じか短い生存期間を持つ。
- メモリがリークすることはメモリ安全性に抵触しない。ので、Rustの良さとして「所有権とライフタイムのおかげでメモリが自動で解放される」と言うのは誤り。
Weak
とRefCell
を使えば、オブジェクト外部で更新されるデータをオブジェクトに保持できるっぽい。- 中間表現を解釈するMiriというコード診断ツールがある。
- 依存ライブラリの型をAPIに公開する場合は依存ライブラリを再エクスポートする。つまり、
// このクレートが依存するクレートを再エクスポート。
// このクレートに依存するクレートが同じくdeplibに依存している場合、
// この再エクスポートがないとdeplibのバージョン違いによりfoo()の引数に適切なオブジェクトを渡せない。
pub use deplib;
// 引数の型として依存クレートの型を公開している。
pub fn foo(arg: deplib::A) { ... }
- ライブラリクレートにはCargo.lockは含めない。
- フィーチャによってパブリックな構造体のフィールドやトレイトメソッドの有無を制御しない。
- Clippy良さそう。
Impression
個別の特化シチュエーションに対するソリューションは書いていないので、各々に関する本を読むことになる。
まえがきやあとがきにも書いてあるが、本書はRustに入門した人が、今後Rustの機能を正しく使うためにある。だから、Rustで何か書いていれば、多くの部分は既知・あるいは「まあそうだよね」と言える内容となっている。勿論、それ以外の部分で学びになるので、読むに越したことはない。
■