Fusion
Fusion

Reputation: 5462

Result and Option unwrapping

I am trying to learn Rust and I would like to understand the conceptual fundamentals. In Rust, we often use Result<T, E> as a return type. Basically, a type, which consists of - Ok() and Err(), and it is up to the caller to handle these.

But what I am kind a surprised is fact, that both Ok() and Err(), have again their "options" -> Namely Some and None.

Example code:

fn integer_divide(a: u32, b: u32) -> Result<u32, String> {
  if b != 0 {
    Ok(a / b)
  } else {
    Err("Division by zero!".into())
  }
} 

let result = integer_divide(5, 0);

if(result.is_err()){
    if(result.err().is_some()){
        // some logic
    }
}

Question

So basically, we need to double check before we get to resulting value of every function (First for Err or Ok, then for Some or None)? If yes, I find this very clunky. Especially in case my integer_divide function, where reliably I am able to say, it can never have a result with Err() of None value.

It would make more sense to me, if we would just unwrap Err(), then check if it's value is None or some other type... Especially in case, where I am 100% sure, it cannot hold None value. Any thoughts appreciated.

Note

I am aware of existence of ? operator. I just want to understand concept.

Upvotes: 3

Views: 4719

Answers (2)

user4815162342
user4815162342

Reputation: 154856

is_err() serves to answer the question "does this result contain an error?". If that's all you're interested in, then you're good to go:

if result.is_err() {
    // logic here
}

Result is just an enum with two well-defined variants, so if you also need to access the value of the error, you can use if let to match the Err variant:

if let Err(e) = result {
   // logic here, `e` contains the error value
}

Finally, if you need to handle both Ok and Err in the same go, use match, as shown in the answer by @prog-fh.

Upvotes: 2

prog-fh
prog-fh

Reputation: 16785

Considering result.err() alone, nothing ensures that result actually contains an error, thus this method cannot return an error every time we invoke it. The usual way in Rust to provide something which is optional is to return an Option, hence the is_some() method. This does not mean that the Result contains such an Option; this Option is created by the err() method just in case result did not contain an error. You know that there is actually an error inside result because you tested just before with result.is_err(); but the designer of the err() method did not know, a long time ago, that you would test is_err() just before calling err().

The usual way to handle result without double check would be

    match result {
        Ok(v) => {
            println!("result is {}", v);
        }
        Err(e) => {
            println!("error: {}", e);
        }
    }

Upvotes: 6

Related Questions