Reputation: 4116
Is there a way to make this code work?
fn set_email(&mut self, email: Option<&str>) -> Result<(), String> {
self.email = email.and_then(|email| {
let email = sanitate(email);
if email.is_empty() {
if self.needs_email {
return Err(String::from("the email is needed"));
}
return None;
}
Some(email)
});
Ok(())
}
As you can see I would like to return an Error if the email is needed and is empty. At the same time I'm in assignment and_then
lambda. How to do?
Upvotes: 0
Views: 108
Reputation: 4902
There is no way to short-circuit the function and return an Err
from the top-level function from within the closure. You need to re-structure your code.
If you make sanitate()
return None
if is_empty()
then you can write it like this, which I find nice and simple:
struct ContainsEmail {
email: Option<String>,
needs_email: bool,
}
impl ContainsEmail {
fn set_email(&mut self, email: Option<&str>) -> Result<(), String> {
self.email = email.and_then(sanitate);
if self.email.is_none() && self.needs_email {
Err(String::from("the email is needed"))
} else {
Ok(())
}
}
}
fn sanitate(email: &str) -> Option<String> {
let sanitized_email = email.trim().to_lowercase(); // TODO: Do something more useful
if sanitized_email.is_empty() {
None
} else {
Some(sanitized_email)
}
}
Upvotes: 1
Reputation: 485
You can use Option::transpose and Some(Ok(..))
struct Email {
email: Option<String>,
needs_email: bool,
}
fn sanitate(s: &str) -> String {
todo!()
}
impl Email {
fn set_email(&mut self, email: Option<&str>) -> Result<(), String> {
self.email = email.and_then(|email| {
let email = sanitate(email);
if email.is_empty() {
if self.needs_email {
return Some(Err(String::from("the email is needed")));
}
return None;
}
Some(Ok(email))
}).transpose()?;
Ok(())
}
}
Upvotes: 1