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
