使用结果有什么好处? [英] What's the benefit of using a Result?

查看:51
本文介绍了使用结果有什么好处?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不明白为什么 Result 存在于 Rust 中.我可以看到 Option 是如何有用的,但是使用 Result 似乎只是不必要地使代码复杂化.

I don't understand why Result exists in Rust. I can see how Option can be useful, but using Result just seems to complicate code unnecessarily.

考虑以下示例:

#[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() 来返回结果.

The only thing I can see is that it minorly increases the convenience of function writers, as you can simply call Ok() and Err() to return results.

我看到有些人说它可以使用条件,但事实并非如此;您可以使用元组很好地使用条件.(注意——条件"是 Rust 的一个特性,在 1.0 之前被移除)

I've seen some people saying its so you can use conditions, but that's not true at all; you can use conditions perfectly well using tuples. (Note — "conditions" were a feature of Rust that were removed before 1.0)

我也看到有人说 Result 比返回元组的性能更高,但是 Result 元组,所以我不明白这是怎么回事.

I've also seen some people saying that Result is more performant that returning a tuple, but Result is a tuple, so I don't see how this can be the case.

推荐答案

让我们考虑 Result的定义:

Let's consider the definition of Result:

/// `Result` is a type that represents either success (`Ok`) or failure
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
#[must_use]
pub enum Result<T, E> {
    /// Contains the success value
    Ok(T),

    /// Contains the error value
    Err(E)
}

提炼到重要的位,它是 enum Result{ Ok(T), Err(E) }.

Distilled to the bits that matter, it's enum Result<T, E> { Ok(T), Err(E) }.

那不是元组(T, E);相反,它是要么一个T(OK)一个E(错误).

That is not a tuple (T, E); rather, it is either a T (OK) or an E (error).

如果使用元组 (T, E),则必须同时定义 T E>.对于您的 returns_tuple,这意味着将 0 定义为一个魔术值并向您的 MyErr 枚举、None 添加一个新变体.None 不是错误;如此建模在语义上是不合理的.由于穷举匹配的要求,它随后也会传播到其他地方.

If you use a tuple (T, E), you must define both the T and the E. For your returns_tuple, that meant defining 0 as a magic value and adding a new variant to your MyErr enumeration, None. None is not an error; it is semantically unsound to model it thus. It also then propagates to other places because of the requirement of exhaustive matching.

当您处理更复杂的类型时,定义一个虚拟值可能不太可行或成本更高.作为概括,拥有虚拟值不是一个好的计划.很有可能在某个阶段,您实际上会尝试使用它们.

When you are dealing with more complex types, defining a dummy value may be less feasible or more expensive. As a generalisation, having dummy values is not a good plan. It's far too likely that somewhere down the track you will actually try to use them.

Rust 有一个很好的类型系统,可以让你避免这类问题.

Rust has a good type system which allows you to avoid these sorts of problems.

在我看来你已经错过了 Rust 匹配的力量;事实上,从枚举中获取值的唯一方法是模式匹配;因此,像 Result.ok()Result.err()Option.unwrap() 之类的东西都是在模式匹配方面实现的.

It looks to me like you've missed the power of Rust's matching; in fact, the only way to get a value out of an enum is pattern matching; in consequence, things like Result.ok(), Result.err() and Option.unwrap() are implemented in terms of pattern matching.

现在让我们以更好地展示 Rust 的方式编写您的示例.

Now let's write your example in a way that shows Rust in a better light.

#[derive(PartialEq, Eq, Debug)]
enum MyErr {
    // Now we don't need that phoney None variant.
    FailOne,
}

fn returns_result() -> Result<u8, MyErr> {
    Err(MyErr::FailOne)
}

#[test]
fn test_check_return_values() {
    match returns_result() {
        Ok(num) => println!("result: Is OK: {}", num),
        Err(MyErr::FailOne) => println!("result: Failed One"),
    }
}

这篇关于使用结果有什么好处?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆