如何定位Rust中函数调用链中仅出现一次的失败函数?
问题描述
我定义了以下三个函数:
fn f(i: i32) -> Option<i32> { Some(1) } fn g(i: i32) -> Option<i32> { Some(1) } fn h(i: i32) -> Option<i32> { Some(1) }
目前我用嵌套的map调用它们:
let x = f(1).map(|j| g(j).map(|k| h(k)));
现在我想添加错误信息,明确指出是哪个函数调用失败了。虽然可以在map里打印信息,但可读性太差。我想要实现类似下面的效果(注:原示例写法存在逻辑问题,?会在遇到None时直接返回,无法进入后续的match分支):
match h(g(f(1)?)?) { Some(Some(Some(x))) => print "success", Some(Some(None)) => print f has failed, Some(None) => print g has failed, None => print h has failed, }
解决方案
要精准定位错误,最合理的方式是把Option转换成Result类型——因为Result可以携带具体错误信息。下面提供几种实现方式:
方法1:在调用时包装为Result
直接在调用过程中把每个Option转换成带错误信息的Result,用闭包配合?简化链式调用:
fn main() { let result = (|| { let j = f(1).ok_or("f has failed")?; let k = g(j).ok_or("g has failed")?; let x = h(k).ok_or("h has failed")?; Ok(x) })(); match result { Ok(x) => println!("success, value: {}", x), Err(msg) => println!("{}", msg), } } fn f(i: i32) -> Option<i32> { Some(1) } fn g(i: i32) -> Option<i32> { Some(1) } fn h(i: i32) -> Option<i32> { Some(1) }
只要某个函数返回None,对应的ok_or就会把它转为Err,链式调用立即终止,最终match能直接捕获到对应错误信息。
方法2:修改函数返回类型为Result(若允许)
如果可以修改原函数,直接让它们返回Result<i32, &'static str>会更直观:
fn main() { let result = (|| { let j = f(1)?; let k = g(j)?; let x = h(k)?; Ok(x) })(); match result { Ok(x) => println!("success, value: {}", x), Err(msg) => println!("{}", msg), } } fn f(i: i32) -> Result<i32, &'static str> { Ok(1) } fn g(i: i32) -> Result<i32, &'static str> { Ok(1) } fn h(i: i32) -> Result<i32, &'static str> { Ok(1) }
函数需要返回失败时,直接返回Err("f has failed")即可,后续调用会自动传递错误。
方法3:用and_then链式处理(无闭包和?)
如果不想用闭包和?,可以用and_then链式处理,同时携带错误信息:
fn main() { let result = f(1) .ok_or("f has failed") .and_then(|j| g(j).ok_or("g has failed")) .and_then(|k| h(k).ok_or("h has failed")); match result { Ok(x) => println!("success, value: {}", x), Err(msg) => println!("{}", msg), } } fn f(i: i32) -> Option<i32> { Some(1) } fn g(i: i32) -> Option<i32> { Some(1) } fn h(i: i32) -> Option<i32> { Some(1) }
先把f(1)的Option转为Result,之后用and_then依次处理后续函数,每个步骤都绑定对应的错误信息。
内容的提问来源于stack exchange,提问作者Pierre-olivier Gendraud
相关产品推荐
相关产品推荐

