What's the benefit of using a Result?

后端 未结 1 1694
后悔当初
后悔当初 2020-12-05 23:50

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 unne

相关标签:
1条回答
  • 2020-12-06 00:00

    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)
    }
    

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

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

    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 has a good type system which allows you to avoid these sorts of problems.

    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.

    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"),
        }
    }
    
    0 讨论(0)
提交回复
热议问题