The Result Type
Result is Rust's way of saying an operation either worked and gives you an answer, or failed and tells you why.enum Result<T, E> {
Ok(T),
Err(E),
}
match result {
Ok(value) => expression,
Err(e) => expression,
}
What Is Result
Result<T, E> is an enum with two variants: Ok(value) for success carrying a T, and Err(error) for failure carrying an E. It's the standard way Rust represents fallible operations.
Example: What Is Result
// Define the function `divide` taking `a`, `b` and returning a `Result<f64, String>`
fn divide(a: f64, b: f64) -> Result<f64, String> {
// Check whether `b == 0.0`
if b == 0.0 {
Err(String::from("division by zero"))
// Otherwise, run this branch
} else {
Ok(a / b)
}
}
// Entry point: execution of the program starts here
fn main() {
// Print "{:?}" to the console, substituting in `divide(10.0, 2.0)` (with a trailing newline)
println!("{:?}", divide(10.0, 2.0));
}
Login to try C/C++/Java/PHP code in the editor
Matching on Result
match lets you explicitly handle both the success and failure cases of a Result, extracting the value or the error as needed.
Example: Matching on Result
// Define the function `divide` taking `a`, `b` and returning a `Result<f64, String>`
fn divide(a: f64, b: f64) -> Result<f64, String> {
// Check whether `b == 0.0`
if b == 0.0 {
Err(String::from("division by zero"))
// Otherwise, run this branch
} else {
Ok(a / b)
}
}
// Entry point: execution of the program starts here
fn main() {
// Match on `divide(5.0, 0.0)` and branch by pattern
match divide(5.0, 0.0) {
Ok(value) => println!("Result: {}", value),
Err(e) => println!("Error: {}", e),
}
}
Login to try C/C++/Java/PHP code in the editor
Parsing Returns a Result
Many standard library operations that can fail, like parsing a string into a number, return a Result so the caller must decide how to handle a malformed input.
Example: Parsing Returns a Result
// Entry point: execution of the program starts here
fn main() {
// Declare an immutable variable `input`, set to `"42"`
let input = "42";
// Declare an immutable variable `parsed` (a `Result<i32, _>`), set to `input.parse()`
let parsed: Result<i32, _> = input.parse();
// Match on `parsed` and branch by pattern
match parsed {
Ok(n) => println!("Parsed number: {}", n),
Err(_) => println!("Could not parse"),
}
}
Login to try C/C++/Java/PHP code in the editor
Result vs Option
Option signals whether a value is present at all, while Result additionally carries information about why an operation failed, making it the better choice whenever the reason for failure matters.
Example: Result vs Option
// Define the function `safe_divide` taking `a`, `b` and returning a `Result<i32, String>`
fn safe_divide(a: i32, b: i32) -> Result<i32, String> {
// Check whether `b == 0`
if b == 0 {
Err(String::from("cannot divide by zero"))
// Otherwise, run this branch
} else {
Ok(a / b)
}
}
// Entry point: execution of the program starts here
fn main() {
// Print "{:?}" to the console, substituting in `safe_divide(10, 2)` (with a trailing newline)
println!("{:?}", safe_divide(10, 2));
// Print "{:?}" to the console, substituting in `safe_divide(10, 0)` (with a trailing newline)
println!("{:?}", safe_divide(10, 0));
}
Login to try C/C++/Java/PHP code in the editor
- Ignoring a
Resultreturned by a function -- the compiler warns about an unusedResultsince errors could be silently dropped. - Assuming
ResultandOptionare interchangeable --Resultcarries error information, whileOptionjust signals absence. - Trying to use the
Okvalue directly without matching or unwrapping theResultfirst.
Result<T, E>represents either success (Ok(value)) or failure (Err(error)).- Functions that can fail, like parsing or file I/O, typically return a
Resultinstead of panicking directly. matchis the most explicit way to handle both theOkandErrcases of aResult.- Rust's compiler warns when a
Resultis left unused, nudging you to handle potential errors.
Chapter Quiz — Complete all 6 topics to unlock
0/6 topics done
Complete these topics first: