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はエラーが発生する可能性がある時に使う