本文へスキップ
BecomeCoder

Rustコース · 第8章 コレクションとエラー処理 · レッスン34

Result ― 失敗を値で扱う

ブラウザで完結

導入

ファイルが開けない、数値に変換できない——処理は失敗します。多くの言語は「例外(try/catch)」で扱いますが、Rust には例外がありません。代わりに、失敗を Resultというで返します。「成功か失敗か」を、Option と同じく型で明示するのです。

説明

Result<T, E> は標準ライブラリの enum です。

enum Result<T, E> {
    Ok(T),    // 成功(中身は成功値 T)
    Err(E),   // 失敗(中身はエラー情報 E)
}

失敗しうる処理は、この Result を返します。中身を使うには、Option と同様に Err の場合を必ず考えさせられます

fn main() {
    // 文字列 → 数値の変換は失敗しうる → Result を返す
    let a: Result<i32, _> = "42".parse::<i32>();
    let b: Result<i32, _> = "abc".parse::<i32>();

    match a {
        Ok(n) => println!("成功: {n}"),
        Err(e) => println!("失敗: {e}"),
    }

    // よく使うメソッド
    let n = "10".parse::<i32>().unwrap_or(0);   // 失敗なら 0
    println!("{n}");
}

// 自分でエラーを返す関数
fn divide(a: f64, b: f64) -> Result<f64, String> {
    if b == 0.0 {
        Err(String::from("0では割れません"))    // 失敗を Err で返す
    } else {
        Ok(a / b)                                // 成功を Ok で返す
    }
}
  • "42".parse::<i32>() … 変換は失敗しうるので Result を返す。Ok(42)Err(...)
  • matchOk/Err を分け、それぞれ処理します。「失敗を無視してそのまま使う」ことは型的にできません。
  • unwrap_or(既定) … 失敗時の既定値。手軽ですが、失敗を握りつぶすので使いどころに注意。
  • unwrap() … 成功なら中身、失敗ならパニックして停止。手早い試作やテストでは便利ですが、本番コードでは避け、ちゃんと Err を処理します。

エラーが「戻り値の型」に現れるので、関数のシグネチャを見るだけで「これは失敗しうる処理だ」と分かります。例外のように「どこから飛んでくるか分からない」ことがなく、失敗の扱いがコード上で追跡できるのが Rust 流です。

試すには

"abc".parse::<i32>().unwrap() はパニックします。matchunwrap_orErr を処理すれば安全に扱えます。「失敗も普通の値」という感覚——Result を受け取ったら開ける——を掴みましょう。次のレッスンで、この処理をもっと簡潔にする ? を学びます。

実際に動かしてみよう

下のエディタにRustを書いて「実行」を押すと、学習用シミュレータが println! の出力を表示します(本物のrustcではなく、教材の範囲を再現した軽量エンジンです)。struct・enum・match・トレイト・Vec/String/HashMap・Option/Result なども動きます。本文の例を書き換えて動かしてみましょう(所有権・借用チェッカーのコンパイルエラーは再現しないため、動きの確認用として使ってください)。

Rust — ブラウザ内で実行(学習用シミュレータ)

Rustの教材サブセットを動かす学習用シミュレータを読み込みます(本物のrustcではなく、動きを再現した軽量な自作エンジンです)。
スクロールして表示された時点でも自動で読み込まれます。