Unwrap and Its Uses in Rust

Nilesh Katuwal Jun 06, 2022
Unwrap and Its Uses in Rust

This article will teach about unwrap and its uses in Rust.

unwrap in Rust

In Rust, to unwrap something means to issue the following command: “Give me the result of the computation, and if there was an error, panic and stop the program.” Because unwrapping is such a straightforward process, it would be beneficial for us to demonstrate the code for it.

However, we need to investigate the Option and Result types before we can do that.

Option Type

The Option type is a way to express the possibility of absence using Rust’s type system. Encoding the possibility of absence into the type system is crucial because it forces the compiler to force the programmer to deal with the absence.

When absence is possible, the enum named Option<T> from the std library is used. It takes the form of one of two options.

  1. Some(T) - An element of type T has been identified.
  2. None - No element was detected.

These situations may be handled using match explicitly or implicitly with unwrap. Implicit handling returns either the inner element or panics.

Syntax:

enum Option<T> {
    None,
    Some(T),
}

Example to find the extension of file name:

fn find(haystack: &str, words: char) -> Option<usize> { haystack.find(words) }
fn main() {
    let name_of_file = "file.doc";
    match find(name_of_file, '.') {
        None => println!("Extension could not be found."),
        Some(i) => println!("The extension of file is: {}", &name_of_file[i+1..]),
    }
}

Output:

The extension of file is: doc

Note that panic can be customized manually with expect, but unwrap produces less relevant output than explicit handling. In the example below, explicit handling produces a more controlled outcome while keeping the option to panic if needed.

fn adult_man(food: Option<&str>) {
    match food {
        Some("pasta") => println!("The food does not taste right."),
        Some(inner)   => println!("{}? It could be nice.", inner),
        None          => println!("No good food? Nevertheless."),
    }
}

fn food(food: Option<&str>) {
    let interior = food.unwrap();
    if interior == "pasta" { panic!("Ummmmmm!!!!"); }

    println!("I am glad to have {}s!!!!!", interior);
}

fn main() {
    let bruschetta  = Some("Bruschetta");
    let pasta = Some("pasta");
    let void  = None;

    adult_man(bruschetta);
    adult_man(pasta);
    adult_man(void);

    let spaghetti = Some("spaghetti");
    let nothing = None;

    food(spaghetti);
    food(nothing);
}

All food is handled explicitly using match in the above code for the first.

All the food is handled implicitly using unwrap for the section function. Unwrap returns a panic when it receives none.

Output:

Bruschetta? It could be nice.
The food does not taste right.
No good food? Nevertheless.
I am glad to have spaghettis!!!!!

Result Type

Result is a more robust version of Option. Unlike Option, which expresses the possibility of absence, Result expresses the potential of error.

The error is typically used to indicate why the execution of a computation failed. This is a generalized form of the word Option.

Syntax:

enum Result<T, E> {
    Ok(T),
    Err(E),
}