使用结果有什么好处?

 我是小崔来啦 发布于 2023-01-19 21:43

我不明白为什么ResultRust会存在.我可以看到它是如何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 {
    // 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()返回结果.

我见过有些人说它,所以你可以使用条件,但这根本不是真的; 你可以使用元组完美地使用条件.(注意 - "条件"是在1.0之前删除的Rust的一个特性)

我也看到有些人说Result返回一个元组更高效,但是Result 一个元组,所以我不明白这是怎么回事.

1 个回答
  • 让我们考虑以下定义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<T, E> { Ok(T), Err(E) }.

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

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

    当您处理更复杂的类型时,定义虚拟值可能不太可行或更昂贵.作为概括,具有虚拟值并不是一个好的计划.在轨道上的某个地方你很可能会尝试使用它们.

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

    在我看来,你已经错过了Rust匹配的力量; 实际上,从枚举中获取值的唯一方法是模式匹配; 结果,事情喜欢Result.ok(),Result.err()并且Option.unwrap()在模式匹配方面实现.

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

    #[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"),
        }
    }
    

    2023-01-19 21:53 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有