2.12 Error Handling
Rust avoids exceptions, instead favoring Result<T, E> for recoverable errors and Option<T> for optional values. Both are special enums typically evaluated with the match construct.
2.12.1 Result Type
fn divide(a: f64, b: f64) -> Result<f64, String> { if b == 0.0 { Err(String::from("Cannot divide by zero")) } else { Ok(a / b) } } fn main() { match divide(4.0, 2.0) { Ok(result) => println!("Result is {}", result), Err(e) => println!("Error: {}", e), } }
The Result type has two variants: Ok for success and Err for failure.
2.12.2 Option Type
fn divide(numerator: f64, denominator: f64) -> Option<f64> { if denominator == 0.0 { None } else { Some(numerator / denominator) } } fn main() { let result = divide(10.0, 2.0); match result { Some(value) => println!("Result: {}", value), None => println!("Cannot divide by zero"), } }
Option has two variants: Some(T) and None, indicating the presence or absence of a value.
2.12.3 Comparison with C
C functions often signal errors by returning a special code (for example, -1) and setting errno:
#include <stdio.h>
#include <errno.h>
int divide(double a, double b, double *result) {
if (b == 0.0) {
errno = EDOM;
return -1;
} else {
*result = a / b;
return 0;
}
}
Rust’s explicit Result and Option types reduce the ambiguity of error codes.