TAKOYAKING’s blog 一覧

TAKOYAKING’s blog

たこ焼き系

Rust: map VS and_then

Rustのmapとand_thenが最初見たときにどちらも加工するという処理なのに、どういう時に使いわけるかイメージできなかったので、まとめてみました。
(Option型にも使用できますが、例はResultにしています。)

map

returnの型: Result
functionの型: FnOnce(T) -> U (Resultではない)
functionはErrなら呼ばれず、Okなら呼ばれる

and_then

returnの型: Result
functionの型: F: FnOnce(T) -> Result (Result!)
functionはErrなら呼ばれず、Okなら呼ばれる

and_thenとmapのサンプル

コンビネータを組み合わせる | Rust by Example

// ファイルからデータを取り出し、値を`Result`として返す。
fn get_data(path: &str) -> Result<String> {
    File::open(path)
        .map_err(|err| err.to_string())
        .and_then(|mut file| {
            let mut contents = String::new();

            // データを`contents`に読み込む。
            file.read_to_string(&mut contents)
                .map_err(|err| err.to_string())
                // `read_to_string`の返り値は無視し、`contents`を返す。
                .map(|_| contents)
        })
}

// 二つのファイルの中身を結合し、新しい`Result`にして返す。
fn concat(filename_a: &str, filename_b: &str) -> Result<String> {
    let (data_a, data_b) = (get_data(filename_a), get_data(filename_b));

    data_a.and_then(|a|
        // `a`と`b`が両方とも`Ok`ならば`Ok`を返し、そうでなければ
        // 先に`Err`を挙げた方の`Err`を返す。
        data_b.and_then(|b| Ok(a + &b))
    )
}

上の例を見るとand_thenはfnの中身がエラーを起こる可能性がある時に使われ、mapはエラーの可能性がない時に使われています。

https://users.rust-lang.org/t/what-is-the-difference-between-map-and-and-then/29108/2
ここにもand_thenは失敗する可能性のある一連の処理の時に使用すると書いてありました。

まとめ

mapはエラーがない時に使う
and_thenはエラーが発生する可能性がある時に使う