Rust
Summary - Error handling
Combine Result, ? and match to build a number-reading function.
Error handling summary
Expected errors are returned with Result<T, E>; bugs stop the program with panic!. ? propagates the error upward and converts it with From. To handle it on the spot, use match, if let, unwrap_or and map_err. Use unwrap/expect only where failure is impossible. Defining your own error enum for application-specific errors is a good habit.
Your own error type
Define an enum for application-specific errors; each variant is a reason for failure:
#[derive(Debug)]
enum HesapHatasi {
Bos,
Gecersiz(String),
}
fn ortalama(s: &str) -> Result<f64, HesapHatasi> {
if s.trim().is_empty() {
return Err(HesapHatasi::Bos);
}
// parse each piece, turn the error into Gecersiz with map_err
todo!()
}
In later lessons you'll implement Display and std::error::Error for this type and combine it with other errors via ?.
Exercise Average calculation
Complete the function fn ortalama(s: &str) -> Result<f64, HesapHatasi> with the HesapHatasi enum above: Bos for empty text; trim each comma-separated piece and convert it to f64, returning Gecersiz(piece) on error (map_err and ?). Print the results for "2,4,9", "" and "1,x" with {:?}, separated by spaces.
Show example solution
#[derive(Debug)]
enum HesapHatasi {
Bos,
Gecersiz(String),
}
fn ortalama(s: &str) -> Result<f64, HesapHatasi> {
if s.trim().is_empty() {
return Err(HesapHatasi::Bos);
}
let mut toplam = 0.0;
let mut adet = 0;
for p in s.split(',') {
let p = p.trim();
let n: f64 = p.parse().map_err(|_| HesapHatasi::Gecersiz(p.to_string()))?;
toplam += n;
adet += 1;
}
Ok(toplam / adet as f64)
}
fn main() {
println!("{:?} {:?} {:?}", ortalama("2,4,9"), ortalama(""), ortalama("1,x"));
}
Test yourself
-
What is the advantage of your own error enum over String errors?
- It always uses less memory
- It doesn't panic
- The compiler requires it
- The caller can behave differently by error kind with match
Show answer
The caller can behave differently by error kind with match — A String can only be read; an enum lets the program decide (e.g. a default for Bos, a warning for Gecersiz).
-
Convert and propagate
let n: f64 = p.parse().map_err(|_| HesapHatasi::Gecersiz(p.to_string()))____;
Show answer
let n: f64 = p.parse().map_err(|_| HesapHatasi::Gecersiz(p.to_string()))?;
-
Group summary
- Result<T, E>
- Expected error
- panic!
- Bug
- ?
- Error propagation
- enum HesapHatasi
- Custom error type
Next lesson: Vowel counter