Result
的 map
在之前的示例中,multiply
中的 panic 并不是健壮的代码。通常,我们希望将错误返回给调用者,以便调用者可以决定如何正确响应错误。
我们首先需要知道我们处理的是哪种错误类型。要确定 Err
类型,我们查看 parse()
,它使用 FromStr
trait 为 i32
实现。因此,Err
类型被指定为 ParseIntError
。
在下面的示例中,直接的 match
语句导致代码总体上更加繁琐。
use std::num::ParseIntError; // With the return type rewritten, we use pattern matching without `unwrap()`. fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> { match first_number_str.parse::<i32>() { Ok(first_number) => { match second_number_str.parse::<i32>() { Ok(second_number) => { Ok(first_number * second_number) }, Err(e) => Err(e), } }, Err(e) => Err(e), } } fn print(result: Result<i32, ParseIntError>) { match result { Ok(n) => println!("n is {}", n), Err(e) => println!("Error: {}", e), } } fn main() { // This still presents a reasonable answer. let twenty = multiply("10", "2"); print(twenty); // The following now provides a much more helpful error message. let tt = multiply("t", "2"); print(tt); }
幸运的是,Option
的 map
,and_then
以及许多其他组合器也为 Result
实现了。Result
包含完整的列表。
use std::num::ParseIntError; // As with `Option`, we can use combinators such as `map()`. // This function is otherwise identical to the one above and reads: // Multiply if both values can be parsed from str, otherwise pass on the error. fn multiply(first_number_str: &str, second_number_str: &str) -> Result<i32, ParseIntError> { first_number_str.parse::<i32>().and_then(|first_number| { second_number_str.parse::<i32>().map(|second_number| first_number * second_number) }) } fn print(result: Result<i32, ParseIntError>) { match result { Ok(n) => println!("n is {}", n), Err(e) => println!("Error: {}", e), } } fn main() { // This still presents a reasonable answer. let twenty = multiply("10", "2"); print(twenty); // The following now provides a much more helpful error message. let tt = multiply("t", "2"); print(tt); }