Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

Rust辞典

  1. トップページ
  2. Rust辞典
  3. Result::unwrap() / expect() / ? 演算子

Result::unwrap() / expect() / ? 演算子

『Result』から値を取り出すメソッドと、エラーを自動的に呼び出し元へ伝播させる『?』演算子の使い方です。特に『?』演算子はエラー処理のボイラープレートを大幅に削減できます。

構文
// Okなら値を返し、Errならパニックします。
let value = result.unwrap();

// Errのとき指定メッセージでパニックします。
let value = result.expect("エラーメッセージ");

// Errのときデフォルト値を返します。
let value = result.unwrap_or(デフォルト値);

// Errのとき呼び出し元にエラーを伝播します(?演算子)。
// Result型を返す関数の中でのみ使用できます。
let value = some_func()?;
メソッド一覧
メソッド・演算子概要
unwrap()『Ok(x)』なら『x』を返します。『Err』の場合はパニックします。プロトタイプやテストコード以外での使用は避けてください。
expect("msg")『unwrap()』と同じですが、パニック時に指定メッセージが表示されます。原因の特定がしやすくなります。
unwrap_or(val)『Err』のときにデフォルト値を返します。エラーを無視して処理を継続したい場合に使います。
unwrap_or_else(fn)『Err(e)』のときにエラー値を受け取るクロージャを実行します。エラーの内容に応じたデフォルト値を返せます。
? 演算子『Ok(x)』なら『x』を返し、『Err(e)』なら即座に呼び出し元へエラーを返します。関数がResult(またはOption)を返す場合のみ使用できます。
ok() / err()ResultをOptionに変換します。『ok()』は『Ok(x)』→『Some(x)』、『Err』→『None』に変換します。
サンプルコード
use std::num::ParseIntError;

// ?演算子でエラーを呼び出し元に伝播します。
fn parse_and_double(s: &str) -> Result<i32, ParseIntError> {
    let n = s.parse::<i32>()?; // パース失敗時は即座にErrを返します。
    Ok(n * 2)
}

// ?を複数回使ったチェーン例です。
fn parse_sum(a: &str, b: &str) -> Result<i32, ParseIntError> {
    let x = a.parse::<i32>()?;
    let y = b.parse::<i32>()?;
    Ok(x + y)
}

fn main() {
    // ?演算子を使った関数の呼び出しです。
    println!("{:?}", parse_and_double("5"));   // Ok(10)
    println!("{:?}", parse_and_double("abc")); // Err(...)

    println!("{:?}", parse_sum("3", "4"));     // Ok(7)
    println!("{:?}", parse_sum("3", "x"));     // Err(...)

    // unwrap_orでエラー時にデフォルト値を使います。
    let n = "abc".parse::<i32>().unwrap_or(0);
    println!("{}", n); // 0

    // unwrap_or_elseでエラー内容を利用します。
    let n = "abc".parse::<i32>().unwrap_or_else(|e| {
        println!("パースエラー: {}", e);
        -1
    });
    println!("{}", n); // -1

    // ok()でResultをOptionに変換します。
    let opt = "42".parse::<i32>().ok();
    println!("{:?}", opt); // Some(42)
}
概要

『?』演算子はRust 1.13で導入されたシンタックスシュガーで、『match』による手動のエラー伝播コードを1文字に短縮できます。『?』は関数の戻り値が『Result』または『Option』でないと使用できません。『main()』関数で使う場合は戻り値を『Result<(), Box<dyn std::error::Error>>』にする必要があります。

エラーの型変換が必要な場合、『?』は自動的に『From』トレイトを呼び出してエラー型を変換します。そのためカスタムエラー型に適切な『From』実装があれば、異なるエラー型が混在する関数でも『?』を統一的に使えます。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。