rustlings 4
Published at 2024/09/07
Errors
It looks like in Rust, we can do some error handling by using a Result - essentially showing that we successfully ran a computation with Ok(T), or returning an error state with Err(String). The caller can then handle error cases appropriately, or choose to panic. I breezed through errors1
and errors2
, and I learned that I can append a suffix of ?
to calls that might result in errors, in order to have those errors immediately returned when they come up, in the Err side of the Result Enum.
Errors3
In this exercise, I arrived at an answer that compiles but left me unsatisfied:
fn main() {
let mut tokens = 100;
let pretend_user_input = "8";
let cost = total_cost(pretend_user_input);
let var_name = match cost {
Ok(cost_total) => cost_total,
Err(error) => {
return;
}
};
let cost = var_name;
if cost > tokens {
println!("You can't afford that many!");
} else {
tokens -= cost;
println!("You now have {} tokens.", tokens);
}
}
Why’s this bad? I don’t like that we’re just returning nothing in the error case. I don’t like that we lost the conciseness of the ?
. I suspect there’s a better way, so I ask for a hint. It seems that
If other functions can return a `Result`, why shouldn't `main`? It's a fairly common convention to return something like Result<(), ErrorType> from your main function.
The unit (`()`) type is there because nothing is really needed in terms of positive
results.
Returning a Result from main seems like a fine idea, though I didn’t think of it!
This is what I end up with - still satisfies the prompt and compiles, but it is closer to what the hint implies.
fn main() -> Result<(), ParseIntError>{
let mut tokens = 100;
let pretend_user_input = "8";
let cost = total_cost(pretend_user_input)?;
if cost > tokens {
println!("You can't afford that many!");
} else {
tokens -= cost;
println!("You now have {} tokens.", tokens);
}
return Ok(())
}
Errors 5 and the first occurrence of Box
Box
is a … type? container? A type in Rust which provides more flexibility than I am used to - it allows for any type implementing a trait. In this exercise I find that a Box containing an error::Error
can be used to tie together a function that can return multiple types of errors.