Sas*_*ssa 1 error-handling functional-programming rust
我有一个功能:
fn test<T: FromStr>(text: &str) -> Result<T, SaleError>
Run Code Online (Sandbox Code Playgroud)
SaleError 在这种情况下是我的自定义错误结构.
我有2个数组,我想将相同的位置值相乘并对结果求和:
fn calculate_result() -> Result<f64, SaleError> {
let q_coms = ["1", "2", "3"];
let v_un_coms = ["1", "2", "3"];
Ok(try!(q_coms.iter().zip(v_un_coms.iter()).fold(0.0, mult_and_sum)))
}
Run Code Online (Sandbox Code Playgroud)
该函数尝试压缩两个数组,然后尝试调用fold该mult_and_sum函数:
fn mult_and_sum(sum: f64, (q_com, v_un_com): (&str, &str)) -> Result<f64, SaleError> {
Ok(sum + try!(test::<f64>(q_com)) * try!(test::<f64>(v_un_com)))
}
Run Code Online (Sandbox Code Playgroud)
据我所知,问题是fold需要一个带签名的函数
fn mult_and_sum(sum: f64, (q_com, v_un_com): (&str, &str)) -> f64
Run Code Online (Sandbox Code Playgroud)
由于该test功能可能会失败,我怎么能使用fold一个Result返回值,所以如果失败,calculate_result将返回Err(SaleError)?
没有必要猜测,错误消息告诉你.我重组了它以使其更加明显:
actual: for<'r, 'r> std::ops::FnMut<(f64, (&'r str, &'r str))>
required: std::ops::FnMut<({float}, (&&str, &&str))>
Run Code Online (Sandbox Code Playgroud)
它还说(expected &str, found str).这是因为你有一片字符串切片(&[&str]).slice的迭代器返回对每个元素的引用,因此值是type &&str.该函数接受a &str,因此不匹配.
另一方面,文档fold显示了它的期望:
fn fold<B, F>(self, init: B, f: F) -> B
where F: FnMut(B, Self::Item) -> B
Run Code Online (Sandbox Code Playgroud)
在单词中:fold通过value(self)获取迭代器,某个type(init: B)的初始值和函数(f: F).该函数采用该类型,迭代器值,并返回type(FnMut(B, Self::Item) -> B).
向后工作,你想要返回一个Result,所以B必须修复它.这意味着你的累加器必须是a Result,大概是你想要的Ok,否则我们将从一开始就失败了.让我们直接实现:
fn calculate_result() -> Result<f64, SaleError> {
let q_coms = ["1", "2", "3"];
let v_un_coms = ["1", "2", "3"];
let pairs = q_coms.iter().zip(v_un_coms.iter());
pairs.fold(Ok(0.0), |acc, (a, b)| {
match acc {
Ok(old) => mult_and_sum(old, (a, b)),
other => other,
}
})
}
Run Code Online (Sandbox Code Playgroud)
哪个可以简化 and_then
pairs.fold(Ok(0.0), |acc, (a, b)|
acc.and_then(|old| mult_and_sum(old, (a, b)))
)
Run Code Online (Sandbox Code Playgroud)
然后可能会有点小:
let pairs = q_coms.iter().cloned().zip(v_un_coms.iter().cloned());
pairs.fold(Ok(0.0), |acc, i| acc.and_then(|old| mult_and_sum(old, i)))
Run Code Online (Sandbox Code Playgroud)
我们cloned用来转换&&str为a &str,但你也可以改变函数来接受a &&str.