map で Result を引き回すときに Err を意識したくない その2
その1はこちらです:
その1では戻り値が i * 2
の i32
型になる話でしたが、その次に考えたかったのは Result
が返ってくるメソッドで引き回すときの話でした。こんな感じで:
// and_then を利用すれば可能だが
// この and_then を省きたい
use anyhow::{anyhow, Result};
fn parse(s: &str) -> Result<i32> {
let res = s.parse::<i32>()?;
Ok(res)
}
fn x2(i: i32) -> Result<i32> {
if i < 50 {
Ok(i * 2)
} else {
Err(anyhow!("too large"))
}
}
fn main() {
let strings = vec!["tofu", "93", "18"];
let numbers: Vec<_> = strings
.into_iter()
.map(parse)
.map(|r| r.and_then(x2))
.map(|r| r.and_then(x2))
.collect();
println!("Results: {:?}", numbers);
// Results: [Err(invalid digit found in string), Err(too large), Ok(72)]
}
anyhow::Result<i32>
な関数を map
でつなげて、最終的な結果を anyhow::Result<i32>
のベクタで得たかったのです。
なんとなくその1の結果からするにイテレータを自作すれば良さそうに思われるのですが、現時点では 実装がさっぱり理解できないので、将来の自分に任せたいと思います…