Rust: Expect vs Unwrap vs ?
Tags: rust, result, option
Published: 2023-01-24 14:12:21

In the previous posts about Option and Result type in Rust language, we have seen the various ways to extract values from them. In this blog post, we're going to explore the difference between `expect`, `unwrap` and `? operator` in Rust

##### Expect method

`expect` method can be used in `Option` or `Result` to provide user-defined message when in case of panic

```rust
    // Declaring variable with Ok() variant of Result type
    let a: Result<i32, &str> = Ok(100);

    // expect() method panics with a provided custom message
    println!("Value of variable a => {}", a.expect("Variable cannot be empty"));
```

##### Unwrap method

`unwrap` method can be used in `Option` or `Result` to return generic system-defined message when in case of panic

```rust
    // Declaring variable with Ok() variant of Result type
    let a: Result<i32, &str> = Ok(100);

    // unwrap() method panics with a generic message
    println!("Value of variable a => {}", a.unwrap());
```

##### ? Operator

`? operator` can be used only for `Result` type. When there are too many function calls that returns `Result` type, error handling will be tedious tasks if you would like to propagate errors up to the call stack. In such case, using `?` manages some of the boilerplate of propagating errors.

In this code example, let us see how to propagate errors without using `? operator`.

```rust
fn print_me(n: i32) -> Result<i32, String> {
    if n < 5 {
        Ok(n)
    } else {
        Err(format!("Given input {n} is invalid!!!"))
    }
}

fn main() -> Result<(), String> {
    // Declaring variable with Ok() variant of Result type
    let a: Result<i32, &str> = Ok(100);

    // expect() method panics with a provided custom message
    println!("Value of variable a => {}", a.expect("Variable cannot be empty"));

    // unwrap() method panics with a generic message
    println!("Value of variable a => {}", a.unwrap());

    // When there is no ? operator to propagate errors
    let r = print_me(2);
    if let Err(x) = r {
        return Err(x)
    }

    let r = print_me(30);
    if let Err(x) = r {
        return Err(x)
    }
    return Ok(())
}
```

If you notice, for every function call `print_me`, we are doing error handling and when in case of `Err` variant, we're propagating errors up to the call stack.

In contrast, let us see how to propagate errors by using `? operator`.

```rust
fn print_me(n: i32) -> Result<i32, String> {
    if n < 5 {
        Ok(n)
    } else {
        Err(format!("Given input {n} is invalid!!!"))
    }
}

fn main() -> Result<(), String> {
    // Declaring variable with Ok() variant of Result type
    let a: Result<i32, &str> = Ok(100);

    // expect() method panics with a provided custom message
    println!("Value of variable a => {}", a.expect("Variable cannot be empty"));

    // unwrap() method panics with a generic message
    println!("Value of variable a => {}", a.unwrap());

    // Propagate errors using ? operator
    print_me(2)?;
    print_me(30)?;
    return Ok(())
}
```

I hope you've enjoyed reading this blog post and it helps to understand the differences between `expect`, `unwrap` and `? operator` usages in Rust language.

You can access the code example used in this blog post from this [link](https://github.com/sivakumar-sivaprakasam/rust-examples/tree/main/expect).

Please feel free to share your comments if any.

Happy reading!!!