Progrust Library.

// dictionary

unwrap.

unwrapは、Option型やResult型に包まれた値を取り出す標準ライブラリのメソッドです12。Some(値)・Ok(値)ならその中身を返し、None・Errならパニックして処理を中断します。パニックの代わりに既定値を返すunwrap_orなど、unwrap以外にもunwrap系のメソッドが複数存在します。

fn find_price(item: &str) -> Option<i32> {
    match item {
        "りんご" => Some(120),
        _ => None,
    }
}

fn main() {
    let apple = find_price("りんご").unwrap(); // Someと分かっているので取り出す
    println!("りんご: {apple}円");

    let banana = find_price("バナナ").unwrap_or(0); // Noneなら0を使う
    println!("バナナ: {banana}円");
}
Playgroundで開く

主なunwrap系メソッド

OptionとResultの両方に、同じ名前のメソッドが用意されています。

メソッド Some / Ok のとき None / Err のとき
unwrap() 中身を返す パニックする
expect("メッセージ") 中身を返す メッセージ付きでパニックする
unwrap_or(既定値) 中身を返す 引数の既定値を返す
unwrap_or_else(処理) 中身を返す 処理を実行し、その戻り値を返す
unwrap_or_default() 中身を返す 型Tの既定値を返す

unwrap_orの引数はSome・Okのときでも必ず評価されるため、既定値の生成にコストがかかる場合は、必要なときだけ評価されるunwrap_or_elseを使います2。

unwrapを使ってよい場面

The Rust Programming Languageは、unwrapとexpectが適切な場面として次の2つを挙げています3。

  • サンプルコード・プロトタイプ・テスト: エラー処理の方針をまだ決めていない段階では、後から手を入れる目印として使えます。テストでは失敗したテスト自体をパニックで落とすことが望ましい挙動です
  • コンパイラより開発者のほうが多くを知っている場合: Errにならないことがコードを読めば分かるものの、その根拠をコンパイラが理解できない場合です

逆に、外部入力やファイル操作のように失敗が現実に起こりうる箇所では、取り出す前にmatch式・if let式・let-else文で分岐するか、?演算子で呼び出し元に処理を委ねます。unwrap系は「取り出せなかったときにどうするか」をその場で決め打ちするメソッドなので、決め打ってよい根拠があるかどうかが選択の基準になります。

fn main() {
    // 直書きの値なので必ず数値として解釈できる
    let people: u32 = "4".parse().expect("人数の指定は数値として正しいはず");
    println!("1人あたり{}円", 3000 / people);
}
Playgroundで開く

補足

unwrap_or_elseとunwrap_or_defaultの細かい規則

unwrap_or_elseが受け取るのはFnOnceを実装する値(通常はクロージャ)で、Result版だけはそれがErrの中身を引数として受け取ります2。unwrap_or_defaultはTがDefaultトレイトを実装している場合にだけ呼べ、数値なら0、文字列型なら空文字列が返ります。

失敗のほうを取り出すunwrap_err

Resultには、Errの中身を取り出すunwrap_errとexpect_errもあります2。Okだった場合はパニックし、そのためにTがDebugを実装している必要があります。処理が確実に失敗することを確認するテストなどで使います。

検査を省くunwrap_unchecked

unwrap_uncheckedはRust 1.58.0で安定化されたunsafeなメソッドで、列挙型のバリアントを検査せずに中身を取り出します12。NoneやErrに対して呼ぶと未定義動作になるため、通常のコードでは使いません。

Footnotes

  1. std::option::Option — 各メソッドのシグネチャのほか、expectの項に「Recommended Message Style」として推奨されるメッセージの書き方が示されています。 ↩ ↩2 ↩3

  2. std::result::Result — unwrap_orの引数が先行評価されること、unwrap・expect・unwrap_err・expect_errがE(またはT)にDebugを要求することが記載されています。 ↩ ↩2 ↩3 ↩4 ↩5

  3. The Rust Programming Language: To panic! or Not to panic! ↩

  4. The Rust Programming Language: Recoverable Errors with Result — 製品品質のコードではunwrapよりexpectを選び、成功するはずの理由を添えることが多いと述べられています。 ↩

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

backlinks 6

  1. 辞書Debugトレイト
  2. 辞書Defaultトレイト
  3. 辞書Option型
  4. 辞書パニック
  5. 辞書論理演算子
  6. 本動かして学ぶRustプログラミング問題集 › 第12章 OptionとResult