-2

There seem to be two obvious ways to handle a Result<T, E> type.

The first is using match, which I believe is used in references such as the Rust Book most frequently.

match some_result {
    Ok(value) => {

    },
    Err(error) => {

    },
}

However, it is fairly trivial to accomplish the same thing using a combination of if is_ok() and unwrap().

if some_result.is_ok() {
    let some_value = some_result.unwrap();

}
else {

}

The match is slightly more elegant in that it doesn't require an additional assignment statement, you already have the type from the name passed to Ok.

There is a partner to unwrap(), unwrap_err() which returns the error, and panics if the result is an Ok rather than an Err.

This means it is possible to do something like:

if some_result.is_ok() {
    let some_value = some_result.unwrap();

}
else {
    let error = some_result.unwrap_err(); // panic if `Ok`

}

However, sometimes the if statement is easier to use as match requires that all branches be compatible in the type they return. (Trivial if () is the return type.)

It seems that the most appropriate choice is context dependent.

Is my understanding of the above points raised correct, or have I misunderstood something which means match should be used instead of if?

FreelanceConsultant
  • 13,167
  • 27
  • 115
  • 225
  • The `if` statement also requires that all branches be compatible in the type they return… – Jmb May 02 '23 at 14:46
  • @Jmb Does `if` always return? I thought its "expression-ness" could be suppressed with `;` ? Maybe I misremember that – FreelanceConsultant May 02 '23 at 14:47
  • There is [`unwrap_err`](https://doc.rust-lang.org/stable/std/result/enum.Result.html#method.unwrap_err). – Jmb May 02 '23 at 14:47
  • 4
    I consider `is_ok()+unwrap()` a Rust antipattern. The fact that that both branches of the if require the same type is a good thing if you use it to initialize something. If you just want to use the value or ignore the error write `if let Ok(x) = some_result { /*...*/ }`. – rodrigo May 02 '23 at 14:48
  • 2
    `.is_ok()` + `.unwrap()` is flagged as a warning by clippy – kmdreko May 02 '23 at 14:48
  • 2
    Note that [`is_ok`](https://doc.rust-lang.org/stable/src/core/result.rs.html#539), [`unwrap`](https://doc.rust-lang.org/stable/src/core/result.rs.html#1084-1086) and [`unwrap_err`](https://doc.rust-lang.org/stable/src/core/result.rs.html#1179-1181) all use `match` internally, so `is_ok()` + `unwrap()` + `unwrap_err()` is just a way of doing two (or three) `match`es instead of one. – Jmb May 02 '23 at 14:59

1 Answers1

2

This question is filled with misconceptions.

There seem to be two obvious ways

There are more than two. For one, you have not considered the ? operator, which would allow you to elegantly raise errors to the caller.

sometimes the if statement is easier to use as match requires that all branches be compatible in the type they return

if has that exact same effect when used as an expression. Regardless of whether you intend to use if or match, all conditional expressions must evaluate to the same type.

let r = Ok(5);
if r.is_ok() {
    r.unwrap()
} else {
   // fails to compile, must return an integer
}

So the point made in favor of the second form is moot. As you well indicated, if the intent is to perform side effects without returning something from the match or if expressions, you can make them return () by appending semi-colons in the blocks.

It seems that the most appropriate choice is context dependent.

The decision is not that blurry at all! There is hardly a good reason to do if result.is_*() followed by unwrap. Not only is it more verbose and looks uglier, it also has a higher chance of doing redundant checks on the result.

See also:

E_net4
  • 27,810
  • 13
  • 101
  • 139
  • 2
    And `unwrap()` is generally considered a bad sign. It makes code review harder. – Chayim Friedman May 02 '23 at 15:28
  • 1
    @ChayimFriedman On that I would just defer to the old-time matter on [whether to panic or not](https://doc.rust-lang.org/stable/book/ch09-03-to-panic-or-not-to-panic.html), as `unwrap` has its places. – E_net4 May 02 '23 at 15:47
  • Of course there are places when you need to panic, but using `unwrap()` when there is a better alternative makes the reader thinks there can be a panic going on. – Chayim Friedman May 02 '23 at 15:49