DEV Community

Sivakumar
Sivakumar

Posted on

Rust: Expect vs Unwrap vs ?

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

    // 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"));
Enter fullscreen mode Exit fullscreen mode
Unwrap method

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

    // 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());
Enter fullscreen mode Exit fullscreen mode
? 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.

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(())
}
Enter fullscreen mode Exit fullscreen mode

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.

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(())
}
Enter fullscreen mode Exit fullscreen mode

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.

Please feel free to share your comments if any.

Happy reading!!!

Top comments (0)