我正在读《铁锈示例》一书。在本例中,删除Err(e) => return Err(e)
中的return
会导致错误:expected `i32`, found enum `Result``
。为什么?
Err(e) => return Err(e)
和Err(e) => Err(e)
之间有什么区别?
以下是示例中的代码:
use std::num::ParseIntError;
fn main() -> Result<(), ParseIntError> {
let number_str = "10";
let number = match number_str.parse::<i32>() {
Ok(number) => number,
Err(e) => return Err(e),
};
println!("{}", number);
Ok(())
}
let number = match number_str.parse::<i32>() {
Ok(number) => number,
Err(e) => return Err(e),
};
这表示如果number_str.parse::<i32>()
返回Ok
以将number
设置为number
,则i32。如果返回Err
以立即从main
返回作为Result
的Err(e)
,则不设置number
。
这很好,因为number
只能是i32
,而main
确实返回了Result
。
let number = match number_str.parse::<i32>() {
Ok(number) => number,
Err(e) => Err(e),
};
这意味着如果number_str.parse::<i32>()
返回Ok
以将number
设置为number
,则i32与之前相同。如果返回Err
,则将number
设置为Err(e)
,即Result
。
number
不能同时是i32
和Result
,因此会出现编译器错误。
match
的所有臂都必须具有";兼容的";类型。这要么意味着它们都有相同的类型:
fn is_some<T>(opt: &Option<T>) -> bool {
match opt {
// both arms have type bool
Some(_) => true,
None => false,
}
}
或者一些分支需要以某种方式引导控制流离开匹配。
要记住的主要规则是,Rust中的每个变量都需要一个单个类型(忽略寿命的方差(。在您的情况下,如果您没有return
关键字,那么number
的类型是什么?
如果解析成功,则number
将是i32
。如果失败,它将是一个Err(ParseIntError)
。这是不允许的,因此会出现编译错误。
但是,如果是return Err(e)
,则number
将始终是i32
(因为return
会阻止函数的其余部分运行,所以number
不需要类型(。
类似的情况也适用于其他控制流关键字(例如continue
、break
…(,以及保证不会返回的内容,如panic!()
(查看Never
/!
类型以了解更多信息(