Option

Option

std

Rust has no null. Instead, use std::option::Option⮳:

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

Every std::option::Option⮳ is either std::option::Option::Some⮳ and contains a value, or std::option::Option::None⮳, and does not.

fn main() {
    let _some_number = Some(5);

    let absent_number: Option<i32> = None;
    println!("{:?}", absent_number);
}

It is often used with match⮳, if let, or while let:

fn bake_cake(sprinkles: Option<&str>) -> String {
    let mut cake = String::from("A delicious cake...");

    // Add required ingredients

    // Handle optional sprinkles
    if let Some(sprinkle_choice) = sprinkles {
        cake.push_str(
            format!(" with a sprinkle of {}", sprinkle_choice).as_str(),
        );
    } else {
        // sprinkles is None
        cake.push_str(" ready for your decorating touch!");
    }
    cake
}

fn main() {
    print!("{}", bake_cake(Some("rainbow nonpareils")));
}

Use adapters when working with references

std

Extract the value contained in Option

std

These methods extract the contained value in an std::option::Option when it is the Some variant. If the std::option::Option⮳ is None:

Use combinators

std


use std::fs;

fn read_file(filename: &str) -> Option<String> {
    fs::read_to_string(filename)
        // Convert `Result` to `Option`
        .ok()
        // `and_then` applies a function to the wrapped value if it's Some.
        .and_then(|contents| Some(contents.trim().to_string()))
}

fn main() -> anyhow::Result<()> {
    if !std::fs::exists("temp")? {
        std::fs::create_dir("temp")?;
    }
    fs::write("temp/poem.txt", b"Lorem ipsum")?;
    let contents = read_file("temp/poem.txt");

    // Using `match` to process the returned Option.
    match contents {
        Some(poem) => println!("{}", poem),
        None => println!("Error reading file"),
    }
    Ok(())
}