I have input with 2 variables (x and y). I need to check that they are not Null and both of them don't contain "?". I achieved it with my code, but for me it seems not super optimized. Is it possible (for sure it is, but I don't know how) to improve it?
#[derive(Debug)]
pub enum TestError {
ContainsQuestionMark,
}
pub type TestResult = Result<bool, TestError>;
fn main() {
let x = Some(String::from("x"));
let y = Some(String::from("y"));
if x.is_some() && y.is_some() {
let x = x.clone().unwrap();
let y = y.clone().unwrap();
if validate(&x, &y).is_ok() {
out(&x, &y);
}
} else {
println!("x and y are Null");
}
}
fn validate(x: &String, y: &String) -> TestResult {
if x.contains("?") || y.contains("?") {
println!("x or y contains ?");
return Err(TestError::ContainsQuestionMark);
}
Ok(true)
}
fn out(x: &String, y: &String) {
println!("These are x = {x}, y = {y}");
std::process::exit(0);
}
You can use if-let to both check and unwrap options at the same time.
if let Some(x) = &x {
if let Some(y) = &y {
if validate(x, y).is_ok() {
out(x, y);
}
} else {
println!("y is None");
}
} else {
println!("x is None");
}
You could get fancy and match both at the same time by stuffing &x
and &y
into a tuple.
if let (Some(x), Some(y)) = (&x, &y) {
if validate(x, y).is_ok() {
out(x, y);
}
} else {
println!("x or y is None");
}
By the way, it's better to take function parameters as &str
rather than &String
. A &str
can accept not only String
references, but also static strings and string slices that aren't stored in mutable String
buffers. There's no ergonomic cost since &String
references automatically convert into &str
.
fn validate(x: &str, y: &str) -> TestResult {
...
}
fn out(x: &str, y: &str) {
...
}