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)
        })
    })

有趣的是,我有一个。有趣的是,我有一个。