liveBook · Manning

Ok_or_else

As explained in Learn Rust in a Month of Lunches

ok_or_else is a Rust Option method that converts Some to Ok and computes the Err value lazily for None with a closure.

ok_or_else converts an Option into a Result. Some(value) becomes Ok(value); None becomes Err(value produced by a closure). The closure lets you build the error only when it is needed. section 9.1.1

Creating a useful error

company.get_ceo().ok_or_else(|| format!("No CEO found for {}", company.name)) A present CEO becomes Ok("Unknown") or Ok("Brendan McCracken"). A missing CEO produces an Err containing the company name and a timestamp, such as "No CEO found for The Red-Headed League at 2024-01-27T23:11:23". section 9.1.1

struct Company {
    name: String,
    ceo: Option<String>,
}
 
fn get_current_datetime() -> String {                            #1
    "2024-01-27T23:11:23".to_string()
}
 
impl Company {
    fn new(name: &str, ceo: &str) -> Self {
        let ceo = match ceo {
            "" => None,
            name => Some(name.to_string()),
        };
        Self {
            name: name.to_string(),
            ceo,
        }
    }
 
    fn get_ceo(&self) -> Option<String> {
        self.ceo.clone()
    }
}
 
fn main() {
    let company_vec = vec![
        Company::new("Umbrella Corporation", "Unknown"),
        Company::new("Ovintiv", "Brendan McCracken"),
        Company::new("The Red-Headed League", ""),
        Company::new("Stark Enterprises", ""),
    ];
 
    let results: Vec<Result<String, String>> = company_vec
        .iter()
        .map(|company| {
            company.get_ceo().ok_or_else(|| {                    #2
                let err_message = format!("No CEO found for {}",
    company.name);                                               #3
                println!("{err_message} at {}",
    get_current_datetime());                                     #4
                err_message                                      #5
            })
        })
        .collect();
 
    results                                                      #6
        .iter()
        .filter(|res| res.is_ok())
        .for_each(|res| println!("{res:?}"));
}

Browse the complete company example that applies ok_or_else while collecting CEO lookup results. section 9.1.1

How Learn Rust in a Month of Lunches covers it

How deep it goes
Explains the conversion, closure behavior, and company example, but does not develop custom error types.
Examples
Uses optional company CEOs and format!-generated messages containing company names and timestamps.
What it assumes
Assumes familiarity with Option, Result, Some, None, Ok, Err, and closures.
What you can do after
Apply it to turn missing optional data into contextual Result errors using a closure.
How it connects
Connects Option, Result, closures, map, and error handling.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Rust in a Month of Lunches. The section links point to the parts of the book it draws on.