我不明白为什么Rust中存在Result
。我能理解Option
的用处,但是使用Result
似乎只会使代码变得更加复杂。
考虑以下示例:
#[derive(PartialEq, Eq, Debug)]
enum MyErr {
None,
FailOne,
}
fn returns_tuple() -> (u8, MyErr) {
// (1, None) // <-- Success path
(0, MyErr::FailOne)
}
fn returns_result() -> Result<u8, MyErr> {
// Ok(1) // <-- Success path
Err(MyErr::FailOne)
}
#[test]
fn test_check_return_values() {
let x = returns_result();
if x.is_ok() {
println!("result: Is OK: {}", x.unwrap()); // <-- Must use unwrap
} else {
match x.err().unwrap() { // <-- Again, unwrapping
MyErr::None => {}, // Required for match
MyErr::FailOne => println!("result: Failed One"),
}
}
}
#[test]
fn test_check_return_values_2() {
let (y, err) = returns_tuple();
match err {
MyErr::None => println!("tuple: Is OK: {}", y),
MyErr::FailOne => println!("tuple: Failed one"),
}
}
我能看到的唯一好处是它可以稍微提高函数编写者的便利性,因为你可以简单地调用Ok()
和Err()
来返回结果。
有些人说这样做是为了使用条件语句,但这完全不是真的;你可以很好地使用元组来使用条件语句。(注意——“条件”是Rust的一个在1.0之前就被删除的特性)
我也看到一些人说Result
比返回元组更有效率,但Result
实际上是一个元组,所以我不明白这怎么能成立。
Result
通过命名其可能的值来作为文档。这可能看起来很小,但实际上当你写很多代码时,你需要查看返回(a, b)
的函数的文档才能确定发生了什么;谁知道它们在成功时返回1或0,或者根本不是错误值?如果我调用期望Foo
的函数并得到Result<Foo, _>
,我可以确定它正在处理潜在错误,并且我毫不怀疑哪些返回值是成功的值(那些包装在Ok
中的值)。 - sleeparrow