Error Handling
Rust Condition Handling
No exceptions (except panics which cannot [normally] be caught)
Normally indicate using
Option
andResult
.std
says something vaguely likeenum Option<T> { Some(T), None, } enum Result<T, E> { Ok(T), Err(E), }
Definitely read the API docs for
std::option::Option
andstd::result::Result
carefully
Unwrap and Expect
Methods of
Option
andResult
..unwrap()
panics with a generic message on failure,.expect("x")
panics with the message"x"
on failurePanic on
None
orErr
, otherwise return the contents ofSome
orOk
let n = Some(7).unwrap(); // n is now 7 let n = None.unwrap(); // program panics
Pattern Matching
Easiest to understand, but most verbose: just deal with the enum directly
// Print a str backward. let mut s = "hello".to_string(); while let Some(c) = s.pop() { print!("{}", c); } println!(); // Read from stdin with default. let stdin = std::io::stdin(); let mut line = String::new(); match stdin.lock().read_line(&mut line) { Ok(_) => (), Err(e) => line = "".to_string(), }
Try (?)
Rust 2018 has the
?
operator. This takes anOption
orResult
and unwraps if good, early-returns from the calling function with the error otherwisefn read_num() -> Result<u64, Box<dyn std::error::Error>> { use std::io::BufRead; let stdin = std::io::stdin(); let mut line = String::new(); let _ = stdin.lock().read_line(&mut line)?; Ok(line.trim().parse()?) }
More recently, it has become allowed to declare
main()
to return aResult
:fn main() -> Result<(), Box<dyn std::error::Error>>
If
main()
returns anErr
you will get an error message formatted some debuggy way
Error Combinators
It is common to handle errors in a "functional" style using methods provided by
Result
andOption
. This is handy when you want to keep going after an error(0..n).sum().and_then(|s| s / n).or_else(0)
This usage can be worth it, but can also be a bit tricky. It will take some practice