Rust The Option Type

In many programming languages, a variable can hold a special value called null or nil to represent "nothing." This causes endless bugs — you try to use the value, forget it might be null, and the program crashes. Rust does not have null. Instead, it uses the Option type to represent values that might or might not exist.

What Is Option?

Option<T> is an enum built into Rust's standard library. It has two variants:

enum Option<T> {
    Some(T),   ← Contains a value of type T
    None,      ← Contains nothing
}

The T is a placeholder for any type. Option<i32> means "either an integer or nothing." Option<String> means "either a string or nothing."

The Gift Box Diagram

Some(42)   =  [ Box with 42 inside ]   ← You get something
None       =  [ Empty box ]            ← You get nothing

You always receive a box. The question is whether there is anything inside.

Creating Option Values

let age: Option<i32> = Some(25);
let missing: Option<i32> = None;

You do not need to write Option::Some or Option::None because they are imported automatically. Just write Some(value) or None.

Using Option with match

To use the value inside an Option, you must handle both cases — the Some case and the None case. match forces you to deal with both:

fn print_age(age: Option<i32>) {
    match age {
        Some(a) => println!("Age is {}.", a),
        None    => println!("Age is unknown."),
    }
}

fn main() {
    print_age(Some(30));
    print_age(None);
}

Output:

Age is 30.
Age is unknown.

A Real-World Example

Finding an item in a collection returns an Option because the item might not be there:

fn find_score(name: &str) -> Option<u32> {
    if name == "Alice" {
        Some(95)
    } else {
        None
    }
}

fn main() {
    let result = find_score("Alice");

    match result {
        Some(score) => println!("Alice scored {}.", score),
        None        => println!("Alice not found."),
    }
}

Output:

Alice scored 95.

Helpful Option Methods

Rust gives you convenience methods so you do not always need a full match expression.

unwrap()

Extracts the value from Some. Panics if the value is None. Use only when you are certain the value exists:

let x: Option<i32> = Some(10);
let value = x.unwrap();   ← value is 10

let y: Option<i32> = None;
let bad = y.unwrap();     ← Panic: called unwrap on None

unwrap_or(default)

Returns the value if Some, or a default value if None. This is the safest common alternative to unwrap:

let score = find_score("Bob").unwrap_or(0);
println!("Bob's score: {}", score);   ← 0 (Bob not found)

is_some() and is_none()

Check whether an Option holds a value or not:

let x: Option<i32> = Some(5);
println!("{}", x.is_some());  ← true
println!("{}", x.is_none());  ← false

if let with Option

When you only care about the Some case, use if let:

let maybe_name: Option<&str> = Some("Alice");

if let Some(name) = maybe_name {
    println!("Hello, {}!", name);
}

map() — Transform the Inner Value

Apply a function to the value inside Some and return a new Option. If the original is None, map passes None through without running the function:

let score: Option<u32> = Some(80);
let doubled = score.map(|s| s * 2);
println!("{:?}", doubled);  ← Some(160)

let no_score: Option<u32> = None;
let still_none = no_score.map(|s| s * 2);
println!("{:?}", still_none);  ← None

Option vs Null

Language    "No value" concept    Can you forget to check?
--------    ------------------    ------------------------
Java/C#     null                  Yes — NullPointerException at runtime
Python      None                  Yes — AttributeError at runtime
Rust        Option<T>             No  — compiler forces you to handle None

Quick Reference

Option<T>                      ← Type that is Some(T) or None
Some(value)                    ← Has a value
None                           ← Has no value
opt.unwrap()                   ← Get the value (panics on None)
opt.unwrap_or(default)         ← Get the value or a fallback
opt.is_some()                  ← True if Some
opt.map(|v| v + 1)             ← Transform the inner value
if let Some(x) = opt { }       ← Handle the Some case only

Leave a Comment