Skip to the content.

Useful Enums

prelude types:

Result<T, E>

user cases: minigrep,

Result<T, E> is the type used for returning and propagating errors. It is an enum with the variants, Ok(T), representing success and containing a value, and Err(E), representing error and containing an error value.

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

Example:

use std::fs::File;

fn main() {
    let greeting_file_result = File::open("hello.txt");

    let greeting_file = match greeting_file_result {
        Ok(file) => file,
        Err(error) => panic!("Problem opening the file: {error:?}"),
    };
}

Other things:

Option<T>

user cases: stack, threadpool,

Type Option<T> encodes the concept of a value being present or absent.

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

Here is an excerpt from stack:

let mut list = Stack::new();
list.push(1);
list.push(2);
println!("{:?}", list.pop()); // Some(2)
println!("{:?}", list.pop()); // Some(1)
println!("{:?}", list.pop()); // None

Option<T> helps to eliminate the null-reference problems that exist in other languages which have a null value.

null-reference problems : e.g., assuming that something isn’t null when it actually is

// java code
String s = Name();
System.out.println(s.length());

Name() may return a null value for some reason. And then it will throw a NullPointerException if s is null.

By contrast, Rust does not have null value, but uses Option<T> to express a value being present or absent.

For example,

fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        None => None,
        Some(i) => Some(i + 1),
    }
}

let five = Some(5);
let six = plus_one(five);
let none = plus_one(None);

Option<T> and T are different types. You have to convert an Option<T> to a T before you can perform T operations with it. Otherwise, the compiler will give an error.