Open3

Effective Rustを1日1項目づつ読んで雑にメモをする

kazup0nkazup0n

Item 3: Prefer Option and Result transforms to explicit match expressions

元記事

  • Option, ResultNone/Errに興味がない場合はmap/map_err, unwrap/expect, if let を使う
  • メソッドに#[must_use]アノテーションをつけると戻り値のResultを無視したときに警告を出せる
  • 特に?を使うとコード簡潔にすることができる。インライン化されてオーバーヘッドがないのでどんどん使おう
  • エラーの内容が呼び出し側にとって有益ならOptionよりもResultを使う
  • Option<T>, Result<T, E>T変換チャート
kazup0nkazup0n

Item 4: Prefer idiomatic Error types

元記事

  • std::error::Errorの実装はほとんど人手がかからないので用途に応じて自分のエラーに対する実装をする
  • ラップするエラーが複数の種類の場合はラップされる型の情報が必要かどうかで判断する
    • 型が必要ないならanyhowを使い、アプリケーションコードに対して型を隠蔽する
    • 型が必要ならenumでラップする。thiserrorが役に立つ
  • 簡略化のため慣用的なエラーハンドリングにはanyhowの使用を検討する
  • どんな決断であれ型システムで表現しよう

TIPS

ラップするエラー型に対してFromを実装しておくとmap_errしなくてよくなる

impl From<std::io::Error> for MyError {
    fn from(e: std::io::Error) -> Self {
        Self::Io(e)
    }
}
impl From<std::string::FromUtf8Error> for MyError {
    fn from(e: std::string::FromUtf8Error) -> Self {
        Self::Utf8(e)
    }
}

こんな感じで?だけで自動的に変換される

    /// Return the first line of the given file.
    pub fn first_line(filename: &str) -> Result<String, MyError> {
        let file = std::fs::File::open(filename)?; // via `From<std::io::Error>`
        let mut reader = std::io::BufReader::new(file);
        let mut buf = vec![];
        let len = reader.read_until(b'\n', &mut buf)?; // via `From<std::io::Error>`
        let result = String::from_utf8(buf)?; // via `From<std::string::FromUtf8Error>`
        if result.len() > MAX_LEN {
            return Err(MyError::General(format!("Line too long: {}", len)));
        }
        Ok(result)
    }
kazup0nkazup0n

Item 5: Understand type conversions

Rustには3種類の型変換がある

  • 手動: ユーザーが定義した型変換でFromInto traitで実現される
  • 半自動: as キーワードによる明示的なキャスト
  • 自動: 新しい型への暗黙的な型強制

FromとIntoによる型変換

  • 変換に関する4つのtraitがある。すなわちFrom<T>TryFrom<T>Into<T>TryInto<T>である。
  • From<T> for U から Into<U> for Tが導出される
  • 関数引数の型パラメータ境界にfn some_func(t: T) -> () where T: Into<U> とIntoを指定することで暗黙的な変換が行える

asによるキャスト

asによるキャストの対象は以下の2パターンしかない

  • 数値のみを含むC-like enum
  • 整数の変換
    • 安全ではないのでintoまたはfromを使うこと

型強制

以下の6パターンがある

  • 可変参照(&mut T)を非可変参照(& T)に変換する
  • 参照をraw参照に変換する
  • 変数をキャプチャしないクロージャを関数ポインタに変換する
  • arrayをsliceに変換する
  • 具象型をtrait オブジェクトに変換する
  • アイテムのライフタイムを短いライフタイムに変換する