Progrust Library.

// dictionary

Result型.

Result<T, E>は、処理が成功したか失敗したかを表す標準ライブラリ列挙型です1。成功時の値を包むOk(T)と、失敗時のエラー値を包むErr(E)という2つのバリアントを持ちます。同じく2バリアントのOption型が値の「有無」だけを表すのに対し、Resultは失敗した「理由」までエラー値として表現できる点が異なります。

fn split_bill(total: i32, people: i32) -> Result<i32, String> {
    if people == 0 {
        Err("人数が0人です".to_string())
    } else {
        Ok(total / people)
    }
}

fn main() {
    for people in [4, 0] {
        match split_bill(3000, people) {
            Ok(amount) => println!("1人あたり{amount}円"),
            Err(reason) => println!("エラー: {reason}"),
        }
    }
}
Playgroundで開く

?演算子によるエラー伝播

Resultを返す関数の中では、?演算子を使うことでErrの場合にエラー値をFromで変換したうえで即座に呼び出し元へ返せますmatch式を毎回書かずに済むため、失敗しうる処理を連続して呼び出すコードを簡潔に書けます。

fn split_bill(total: i32, people: i32) -> Result<i32, String> {
    if people == 0 {
        return Err("人数が0人です".to_string());
    }
    Ok(total / people)
}

fn print_share(total: i32, people: i32) -> Result<(), String> {
    let amount = split_bill(total, people)?; // Errならここで即座にreturnする
    println!("1人あたり{amount}円");
    Ok(())
}

fn main() {
    if let Err(reason) = print_share(3000, 0) {
        println!("エラー: {reason}");
    }
}
Playgroundで開く

#[must_use]による握りつぶし防止

補足

用途別のResultエイリアス

std::io関連の関数はほとんどがio::Errorをエラー型として返すため、標準ライブラリはpub type Result<T> = result::Result<T, Error>という型エイリアスをstd::io::Result<T>として提供しています2。エラー型を毎回書かずに済み、プレリュードのstd::result::Resultと名前が重複してもio::Resultと書けば区別できます。

Footnotes

  1. std::result::Result#[must_use = "this \Result` may be an `Err` variant, which should be handled“]付きでpub enum Result<T, E> { Ok(T), Err(E) }`と定義されています。 2

  2. std::io::Resultpub type Result<T> = result::Result<T, Error>と定義されています。

この辞書が使われているページ

backlinks 7

  1. 辞書let-else文
  2. 辞書unwrap
  3. 辞書ユニット型
  4. 辞書標準ライブラリ
  5. 辞書変換トレイト
  6. 辞書列挙型
  7. 動かして学ぶRustプログラミング問題集 › 第12章 OptionとResult