GW は引き篭もって Rust で小さなプログラムを書くようにしていたので, その時に感じたことをまとめておく.
Atom (linter-rust) とターミナルで.
Rust を学ぶモチベーションは, 自分の中で C++ の代替を目指したため.
玉石混交だけど.
rust-lldb, rust-gdb がついてきた.
すごい適当な気分でプログラミングしていると, とにかくコンパイラに怒られる. 最初に面食らったのは, ファイルの読み書きを書こうと思ってサンプルコードをコピーして動かしてみるとコンパイルエラーになる.
https://doc.rust-lang.org/1.1.0/std/fs/struct.File.html
これが example とあるので, これを適当にコピーして貼っつけても動かない.
サンプルコード部分に playground へのリンクがあり, 飛んでみると上の様になり, これだと問題ない.
単純な話で, try!
マクロは内部で return
文を展開するので try!
マクロが返そうと
する戻り値の型と関数の戻り値の型が一致しないとコンパイルエラーになる.
最初はマクロを理解しておらず, 最初の example とにらめっこしたまま無駄に時間を消費した.
提供されているライブラリの多くの関数は値を Option<T>
もしくは Result<T,E>
で返してくるため,
素直に取り出そうとするとパターンマッチして分岐を記述する必要がある.
が, パターンマッチが面倒くさい人のために unwrap
メソッドが用意されており Option<T>, Result<T,E>
から
内部の値を取り出すことが出来る.
ただし unwrap
は Option<T>
が Some(v)
, Result<T,E>
が Ok(v)
であった場合のみ正常に動作し,
None
や Err(err)
などであった場合には panic になってしまい, プログラムが不正に停止してしまう.
そこで try!
では Result<T,E>
型の変数に対して, unwrap
の様に展開を試みて, 失敗するようなら return Err(E)
をするというマクロになっている.
この動作は, ふら~っとやってきて「ファイル読み書きサンプルコードは?」という心構えの初学者に理解させるのは少し難しめだと感じた.
Option<T>
の場合でも Result<T,E>
に変換出来るので, 同様に try!
で処理出来てしまう.
さらに省略記法は進み, 今は try!
マクロではなく, Result<T,E>
を返す式の末尾に ?
をつけることで同じ動作になっている. 更に短く.
省略はそれだけではなく, 型名や lifetime パラメータなど様々あるが, この try!
のようなマクロを作れる環境が省略に一番寄与しているように感じる.
いくつかパッケージをのぞいて見ても, パッケージ毎に独自のマクロを定義して省略が行われている様子が見て取れる.
わかりやすい. 引数のコピーコストはない.
Option<T>
とか Result<T,E>
の内部値を取り出して操作して再び包むような操作を map
メソッドで行うが, その際のコピーコストもない(はず).
最高. mutable な方に対して mut
と書かなくてはならない.
これも簡単だけど最初に面食らったので.
String
は公式ドキュメントだと growable string
とあり, 可変長の文字列を表す primitive クラス.
それとは別に str
というクラスもあり, これは固定長の primitive クラス.
growable
配列は Vec<T>
で, 固定長なものはスライスと呼ばれて let a = [1,2,3];
みたいに定義する.
最初の try!
マクロについても触れたように, とにかく標準ライブラリでは Option
やら Result
に包んで返してくれるので
?
構文なりを使わず unwrap
で取り出していくと危険なプログラムが出来あがる.
なので, unwrap
しているところはエラーハンドリングをおざなりにしていることの証でもあるので, もしあとで綺麗に直すつもりがあるのなら目印になる.
https://doc.rust-lang.org/book/error-handling.html
公式でもエラーハンドリングの章は割りと長め. でもここが読めたら割りと達成感がある.
なんだかんだ, まだまだ理解が足りてないので深めていきたい.
今のところ, 簡単なスクリプト用途などでは Ruby
を使う方に習熟度として軍配が上がっているので, その代替になるくらい理解していきたい.
lifetime パラメータの使い所がまだ分からない程度には習熟していない.