Best way to use a default value/None in an enum?

Hi there. I am trying to learn Rust and going through the rust-lang.org book but I am a bit unclear on enums.

Is there a way to use a None/Null or default value for coins that don't have a state? I had tried returning an empty string in the tuple, but it requires the UsState type. Then I just decided to have a UsState::None, but I don't really know if that is good practice or not.

The example in the book just prints the state for a Coin::Quarter but I want to return a state as well (if it's a quarter) as the first element in the tuple else some default value.

#[derive(Debug)]
enum UsState {
    Alabama,
    Massachusetts,
    RhodeIsland,
    None,
}

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter(UsState),
}

fn value_in_cents(coin: Coin) -> (UsState, u8) {
    match coin {
        Coin::Penny => (UsState::None, 1),
        Coin::Nickel => (UsState::None, 5),
        Coin::Dime => (UsState::None, 10),
        Coin::Quarter(state) => (state, 25),
    }
}

fn main() {
    let p: Coin = Coin::Penny;
    println!("{:?}", value_in_cents(p));

    let n: Coin = Coin::Nickel;
    println!("{:?}", value_in_cents(n));

    let d: Coin = Coin::Dime;
    println!("{:?}", value_in_cents(d));

    let mut q: Coin = Coin::Quarter(UsState::Massachusetts);
    println!("{:?}", value_in_cents(q));

    q = Coin::Quarter(UsState::Alabama);
    println!("{:?}", value_in_cents(q));

    q = Coin::Quarter(UsState::RhodeIsland);
    println!("{:?}", value_in_cents(q));
}```

Enums are full-fledged types on their own right. They are not just another syntax for string literals. Enums are not strings.

Usually, you should express missing values using the standard Option type, so you should return Some(state) if the state exists, and None if it's missing.

3 Likes

To expand on @H2CO3's comment, it is idiomatic to use an Option whenever you want to say "X may or may not be present".

In code, it would look like this:

#[derive(Debug)]
enum UsState {
    Alabama,
    Massachusetts,
    RhodeIsland,
}

...

fn value_in_cents(coin: Coin) -> (Option<UsState>, u8) {
    match coin {
        Coin::Penny => (None, 1),
        Coin::Nickel => (None, 5),
        Coin::Dime => (None, 10),
        Coin::Quarter(state) => (Some(state), 25),
    }
}
2 Likes