What is an idiomatic way to deal with this match/Option situation?

pub fn print_result(bcd: &BinaryCalculationData)
{
    let o1 = match bcd.operand_1
    {
        Some(v) => v,
        None => "None"
    };

    let o2 = match bcd.operand_2
    {
        Some(v) => v,
        None => "None"
    };

    let answer = match bcd.answer
    {
        Some(v) => v,
        None => "None"
    };


    println!("{} {} {} = {}", o1, bcd.operation, o2, answer);
}

No dice because v is a i32 and I'm trying to potentially assign &str None as you can see. You can see what I'm trying to do though... I want to "unwrap" these Options so I can print them.

You can print the Option directly with {:?} instead of {}. This will call the Debug version of print.

The question is how do you want to handle optional values that have None?

The idiomatic way to write print_result is to return an Option and use the ? operator to bail early when any optional value cannot be unwrapped: Rust Playground

Alternatively, if you actually want to continue executing the function body (don't bail early), you can use something like Option::map and Option::unwrap_or to transform the i32 to a String: Rust Playground

1 Like

You'd actually want to use unwrap_or_else(|| "None".to_owned()) in this situation because unwrap_or will eagerly evaluate the string-allocating code, whereas unwrap_or_else won't.

3 Likes

I like solution #1 you gave here in this case.

I'm glad that you identified this because I had the impression that I should avoid working with Ok(()) for semantic reasons but actually, this allows us to display errors in the opposite case using ?.

For anyone else who reads this, I also just stumbled upon this article which is obviously a couple years old, but still a bit helpful.

You're absolutely right! Thanks for the reminder.

Within limited scope that also works:

let by_ref = owned.as_ref().unwrap_or("None");
1 Like

This is brilliant. Thank you.