本文へスキップ
BecomeCoder

Rustコース · 第7章 構造体とenum ― データを型で表す · レッスン30

Option ― 「値がないかもしれない」を安全に

ブラウザで完結

導入

多くの言語を悩ませてきたのが null(値がない状態)です。null を持つ変数をうっかりそのまま使い、実行時にクラッシュ——「10億ドルの過ち」とも呼ばれるこのバグを、Rust は Optionで根本から防ぎます。Rust に null はありません。

説明

Option<T> は標準ライブラリの enum で、「値があるか・ないか」を表します。

enum Option<T> {
    Some(T),   // 値がある(中身は T 型)
    None,      // 値がない
}

「値がないかもしれない」ものは、すべてこの Option で包まれて返ってきます。たとえば配列から要素を探す find、割り算の安全版などです。

fn main() {
    let numbers = [1, 2, 3];

    // get は「範囲内なら Some(値)、範囲外なら None」を返す
    let a: Option<&i32> = numbers.get(1);   // Some(&2)
    let b: Option<&i32> = numbers.get(10);  // None

    // 中身を使うには、None の場合も必ず考えさせられる
    match a {
        Some(v) => println!("値は {v}"),
        None => println!("値がない"),
    }
}

ここが決定的に重要です。numbers.get(1)2 を直接返すのではなく、Some(2) という箱に入れて返します。中身を使うには、match などで None の場合を必ず処理しなければなりません。「値があると思い込んでそのまま使う」ことが型のレベルで不可能なのです。だから null 由来のクラッシュが起きません。

毎回 match を書くのが冗長なときは、便利メソッドが使えます。

fn main() {
    let x: Option<i32> = Some(5);

    // if let: 1つのケースだけ処理したいとき
    if let Some(v) = x {
        println!("あった: {v}");
    }

    // unwrap_or: None のときの既定値を指定
    let y: Option<i32> = None;
    println!("{}", y.unwrap_or(0));   // None なので 0

    // map: 中身があれば変換
    let doubled = Some(5).map(|n| n * 2);   // Some(10)
    println!("{:?}", doubled);
}
  • if let Some(v) = x … 「Some のときだけ」を簡潔に書く構文。
  • unwrap_or(既定値)None のときの代わりの値を指定。
  • map(...) … 中身があるときだけ関数を適用(None ならそのまま None)。

Option は「値がないかもしれない」を、null のように隠さず、型として明示します。コンパイラが「ない場合の処理」を必ず書かせてくれるので、実行時の null 参照エラーとは無縁になります。次章では、この考え方をエラー処理に広げた Result を学びます。

試すには

Some(5) の中身を取り出そうと x + 1 と直接書くとエラーになります(Option<i32>i32 は別の型)。必ず matchif letunwrap_or などで「None の場合」を経由させられます。この「箱を必ず開けさせる」設計が、null 安全の正体です。

実際に動かしてみよう

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

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

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