はじめに
Rustは「きちんとしたプログラムを書く時にはいいけど、書き捨てのプログラムを書くには向いていない」と言われることがあるようです。「一般論としては全くその通り」と思う一方で、自分自身を振り返ってみると、これまでPythonで書いていたような書き捨てに近いプログラムも全部Rustで書くようになっています。
なぜ書き捨てのプログラムもRustで書くのかを考えてみると
- 最初は書き捨てだと思っていても、手直ししながら使い続けることは意外と多い
- コンパイラが割と多くのエラーを捕捉してくれるのでデバッグの時間が短くて済む
- 記述量の多さはエディタの補完があってあまり気にならない
といったあたりが理由になっています。
そうはいってもRustがいろいろと面倒な言語であることには違いないので、書き捨てるときは普段のRustプログラミングとは少し違った書き方をした方がより早く書けるのではないかと思います。
この記事ではそのようなときのためのTipsをまとめてみました。他にもありそうならコメント欄でお願いします。
ライフタイムを避ける
なんらかの文字列を構造体に入れたいときに、「この文字列は変更されないから &str
で入れよう」とか思ってしまうかもしれませんが、これはいけません。
struct<'a> A {
name: &'a str,
}
参照を入れるということはライフライム修飾が必須となり、この構造体を扱うあらゆるところにライフタイムが出現することになります。全然書き捨て易くありません。
素直に String
を持たせましょう。
struct A {
name: String,
}
同様にたとえ固定値の配列だったとしても &[u32]
ではなく Vec<u32>
にしましょう。
こうすることで、その構造体を作る度に文字列のメモリコピーが発生したりしますが、現代のマシンにおいて(たいていの場合)メモリコピーなどたいしたことではありません。
clone
も積極的に使うといいでしょう。「Borrow checkerに怒られたらとりあえずclone
する」くらいでもいいと思います。
Rc
やArc
でBorrow checkを回避するというのも考えられますが、そこまでやると書き捨ての範囲を超えてくるような気がします。
unwrapする
Rustでは失敗するかもしれない関数から Result
が返ってくるのでエラー処理をきちんとする必要があります。
しかし書き捨てるときにはエラー処理をする必要はないので、unwrap
で結果を取り出せばいいでしょう。
let mut f = File::open("foo.txt").unwrap();
きちんとしたプログラムでは ?
を使ってエラー処理したり、パニックさせる場合でも expect
を使って理由を明示した方がいいですが、書き捨てる場合はとりあえず unwrap
でいいと思います。
dbg/Debugを使う
何か表示したいときは dbg!
マクロを使うといいでしょう。フォーマットの制御などはできませんが「なんでもいいから表示したい」というときには十分です。このときとりあえず &
で参照にしておくと所有権を取られないので付けておきましょう。
dbg!(&hoge);
これを使うために構造体にはとりあえず #[derive(Debug)]
を付けておくといいでしょう。
examplesをコピペする
何かライブラリを使いたいと思ったときは、そのリポジトリの examples
というディレクトリを探しましょう。たいてい簡単な使用例がコンパイル可能な状態で置かれているので、それをコピペして作業を始めればいいと思います。
examples
ディレクトリはライブラリ本体をCargoでコンパイルすると一緒にコンパイルしてチェックされるので、古くなっていて使えないということはめったにありません。
まとめ
Rustを書き捨てるときのTipsをまとめてみました。Rustのいいところは、ここで書いたような雑な記述をしても、後々のリファクタリングがやりやすいところです。
unwrap
している箇所はgrepすれば一目瞭然なので、そこをちゃんとしたエラー処理に直せばよいですし、clone
しすぎて遅くなっているならその部分だけ改善することもできます。
データ構造に参照を持たせるのはさすがに大改修になってしまいますが、それでも修正が必要な箇所はコンパイルエラーとして明示されるので1個づつ潰していけばなんとかなることが多いです。