Error handling 如何使用具有结果返回值的折叠?
我有一个功能:Error handling 如何使用具有结果返回值的折叠?,error-handling,functional-programming,rust,Error Handling,Functional Programming,Rust,我有一个功能: fn test<T: FromStr>(text: &str) -> Result<T, SaleError> 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::<f
fn test<T: FromStr>(text: &str) -> Result<T, SaleError>
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)))
}
该函数尝试压缩两个数组,然后尝试调用mult_和_sum函数的fold:
fn test<T: FromStr>(text: &str) -> Result<T, SaleError>
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)))
}
由于测试函数可能会失败,我如何使用fold和结果返回值,以便在失败时,计算结果将返回ErrSaleError?错误消息告诉您,无需猜测。我对其进行了重新组织,使其更加明显:
actual: for<'r, 'r> std::ops::FnMut<(f64, (&'r str, &'r str))>
required: std::ops::FnMut<({float}, (&&str, &&str))>
换句话说:fold通过值self接受一个迭代器,一个init:B类型的初始值和一个f:f函数。该函数接受该类型,一个迭代器值,并返回类型FnMutB,self::Item->B
反向工作时,您希望返回一个结果,因此B必须固定为该值。这意味着您的累加器必须是一个结果,可能您希望一个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,
}
})
}
然后可能会小一些,比如:
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)))
我们使用将&&str转换为&str,但您也可以将函数更改为接受&&str。错误消息告诉您,无需猜测。我对其进行了重新组织,使其更加明显:
actual: for<'r, 'r> std::ops::FnMut<(f64, (&'r str, &'r str))>
required: std::ops::FnMut<({float}, (&&str, &&str))>
换句话说:fold通过值self接受一个迭代器,一个init:B类型的初始值和一个f:f函数。该函数接受该类型,一个迭代器值,并返回类型FnMutB,self::Item->B
反向工作时,您希望返回一个结果,因此B必须固定为该值。这意味着您的累加器必须是一个结果,可能您希望一个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,
}
})
}
然后可能会小一些,比如:
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)))
我们使用将&&str转换为&str,但您也可以将函数更改为接受&&str
由于测试函数可能会失败,我如何使用fold和结果返回值呢?如果失败,[如果一个元素是错误]
您的累加器在每次迭代中更改的内容也需要是一个结果!请看以下代码:
let q_coms = ["1", "2", "3"];
let v_un_coms = ["1", "2", "3"];
q_coms.iter()
// We don't need to call `iter()` on `v_un_coms`, because `zip()`
// takes an argument which implements `IntoIterator`
.zip(&v_un_coms)
// As you can see: the starting value is `Ok(0.0)` to say: so far,
// there was no error.
.fold(Ok(0.0), |acc, (a, b)| {
// The `and_then()` method calls the given closure when the `acc`
// (the outer one) is `Ok`. The inner `acc` represents the `Ok`
// value. The closure will then return another `Result`.
acc.and_then(|acc| {
// More fun with `and_then()` and `map()`. Read docs for more
// information.
test::<f64>(a)
.and_then(|a| test::<f64>(b).map(|b| a * b))
.map(|new_product| acc + new_product)
})
})
由于测试函数可能会失败,我如何使用fold和结果返回值呢?如果失败,[如果一个元素是错误]
您的累加器在每次迭代中更改的内容也需要是一个结果!请看以下代码:
let q_coms = ["1", "2", "3"];
let v_un_coms = ["1", "2", "3"];
q_coms.iter()
// We don't need to call `iter()` on `v_un_coms`, because `zip()`
// takes an argument which implements `IntoIterator`
.zip(&v_un_coms)
// As you can see: the starting value is `Ok(0.0)` to say: so far,
// there was no error.
.fold(Ok(0.0), |acc, (a, b)| {
// The `and_then()` method calls the given closure when the `acc`
// (the outer one) is `Ok`. The inner `acc` represents the `Ok`
// value. The closure will then return another `Result`.
acc.and_then(|acc| {
// More fun with `and_then()` and `map()`. Read docs for more
// information.
test::<f64>(a)
.and_then(|a| test::<f64>(b).map(|b| a * b))
.map(|new_product| acc + new_product)
})
})
有趣的是,我有一个。有趣的是,我有一个。