Caution

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

Rust辞典

  1. トップページ
  2. Rust辞典
  3. Option::map() / and_then() / is_some()

Option::map() / and_then() / is_some()

『Option』を変換・チェーンするメソッド群です。取り出してから処理するのではなく、『Option』のまま変換をつなげることで、値の有無をチェックしながら簡潔に処理を記述できます。

構文
// Someのとき値をクロージャで変換し、Noneはそのまま伝播します。
let mapped = option.map(|x| x * 2);

// Someのときにオプション値を返すクロージャを適用します(フラット化)。
let chained = option.and_then(|x| some_func(x));

// Noneのときに代替のOptionを返します。
let fallback = option.or(Some(42));

// Noneのときにクロージャで代替のOptionを生成します。
let fallback = option.or_else(|| Some(compute()));

// Someかどうかを真偽値で返します。
let has_value = option.is_some();

// Noneかどうかを真偽値で返します。
let is_empty = option.is_none();
メソッド一覧
メソッド概要
map(fn)『Some(x)』のとき『fn(x)』の結果を『Some』で包んで返します。『None』はそのまま『None』になります。値の型変換に使います。
and_then(fn)『Some(x)』のとき『fn(x)』を呼び出し、その戻り値(Option型)をそのまま返します。Optionを返す処理を連鎖させる際に使います。
or(opt)『Some』ならそのまま、『None』なら引数の『opt』を返します。フォールバック値の提供に使います。
or_else(fn)『None』のときだけクロージャを実行し、その結果を返します。
is_some()値が『Some』なら『true』を返します。条件分岐の簡潔な記述に使います。
is_none()値が『None』なら『true』を返します。
filter(fn)『Some(x)』のとき条件クロージャが『false』を返したら『None』に変換します。
サンプルコード
fn parse_positive(s: &str) -> Option<u32> {
    s.parse::<i32>().ok()                // 文字列を整数に変換します。
        .and_then(|n| if n > 0 { Some(n as u32) } else { None }) // 正の数だけ残します。
}

fn main() {
    let some_val: Option<i32> = Some(5);
    let none_val: Option<i32> = None;

    // mapで値を変換します。
    println!("{:?}", some_val.map(|x| x * 10)); // Some(50)
    println!("{:?}", none_val.map(|x| x * 10)); // None

    // and_thenでOption返し関数をチェーンします。
    println!("{:?}", parse_positive("10")); // Some(10)
    println!("{:?}", parse_positive("-5")); // None
    println!("{:?}", parse_positive("abc")); // None

    // orでNoneのときにフォールバックします。
    println!("{:?}", none_val.or(Some(99)));   // Some(99)
    println!("{:?}", some_val.or(Some(99)));   // Some(5)

    // filterで条件を満たさないSomeをNoneに変換します。
    println!("{:?}", some_val.filter(|&x| x > 3)); // Some(5)
    println!("{:?}", some_val.filter(|&x| x > 10)); // None

    // is_some / is_noneで真偽値を確認します。
    println!("{}", some_val.is_some()); // true
    println!("{}", none_val.is_none()); // true
}
概要

『map()』と『and_then()』の違いは戻り値にあります。クロージャが通常の値を返すなら『map()』を、『Option』を返すなら『and_then()』を使います。『and_then()』でクロージャの戻り値が『Option』でないとコンパイルエラーになります。

これらのメソッドを連鎖させることで、「値があれば変換 → 条件チェック → 変換」という処理を『match』を多重に書かずにパイプライン状に記述できます。Rustではこのスタイルを「コンビネータ」と呼び、関数型プログラミングの考え方を取り入れた記法です。

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