Elegant way to apploy "or" between Option and Result

Hello there.

I'm working on a rust project. which requires lot's of code to load a backup value when current value is None. Is there a elegant way to implement this without a helper trait?

use anyhow::anyhow;
use std::error::Error;

pub trait OptionUtil<T> {
    fn ok_or_else_result<E>(self, f: impl FnOnce() -> Result<T, E>) -> Result<T, E>;
}

impl<T> OptionUtil<T> for Option<T> {
    fn ok_or_else_result<E>(self, f: impl FnOnce() -> Result<T, E>) -> Result<T, E> {
        match self {
            Some(v) => Ok(v),
            None => f(),
        }
    }
}

fn main() -> Result<(), Box<dyn Error>> {
    let config1: Option<i32> = None;

    // my current solution
    let config1_final = config1.ok_or_else_result(load_backup_value)?;
    println!("hello {}", &config1_final);

    // this works but can not avoid call `load_backup_value`
    // when config1 is Some
    let config1_final = config1.unwrap_or(load_backup_value()?);
    println!("hello {}", &config1_final);

    // this works but a useless Error created
    let config1_final = config1
        .ok_or(anyhow!("some dummy error"))
        .or_else(|_| load_backup_value())?;
    println!("hello {}", &config1_final);
    Ok(())
}

fn load_backup_value() -> Result<i32, Box<dyn Error>> {
    Ok(42) // some code might return Err
}

(Playground)

Output:

hello 42
hello 42
hello 42

Why not just this? No need to create "normal big error".

    let config1_final = config1
        .ok_or(())
        .or_else(|_| load_backup_value())?;

Also, I have found Option::map_or_else

    let config1_final = config1.map_or_else(load_backup_value, Ok)?;
5 Likes