Rust Interview Questions
Rust
Web DevelopmentIoTQuestion 13
What is the Result type in Rust?
Answer:
The Result type in Rust is an enum used for error handling. It represents either a success or a failure, providing a type-safe way to handle operations that can fail. The Result type is defined in the standard library and is commonly used for functions that can produce errors.
Definition
The Result enum is defined as follows:
enum Result<T, E> {
Ok(T),
Err(E),
}
Ok(T): Indicates that the operation was successful and contains a value of typeT.Err(E): Indicates that the operation failed and contains an error of typeE.
Usage
Creating and Returning Result
You can create and return a Result from a function to indicate success or failure:
fn divide(numerator: f64, denominator: f64) -> Result<f64, String> {
if denominator == 0.0 {
Err(String::from("Cannot divide by zero"))
} else {
Ok(numerator / denominator)
}
}
fn main() {
match divide(4.0, 2.0) {
Ok(result) => println!("Result: {}", result),
Err(e) => println!("Error: {}", e),
}
match divide(4.0, 0.0) {
Ok(result) => println!("Result: {}", result),
Err(e) => println!("Error: {}", e),
}
}
Unwrapping Result
If you are sure that a Result is Ok, you can use the unwrap method. However, this will panic if the Result is Err.
fn main() {
let result = divide(10.0, 2.0);
println!("Unwrapped result: {}", result.unwrap());
// This will panic
// let error_result = divide(10.0, 0.0);
// println!("Unwrapped error: {}", error_result.unwrap());
}
Handling Errors Gracefully
You can use methods like unwrap_or, unwrap_or_else, and unwrap_or_default to provide default values or handle errors more gracefully.
fn main() {
let result = divide(10.0, 2.0).unwrap_or(0.0);
println!("Result or default: {}", result);
let result = divide(10.0, 0.0).unwrap_or_else(|err| {
println!("Handling error: {}", err);
0.0
});
println!("Result or handled error: {}", result);
}
Chaining Operations with and_then
You can chain operations that return Result using the and_then method.
fn square_root(number: f64) -> Result<f64, String> {
if number < 0.0 {
Err(String::from("Cannot take the square root of a negative number"))
} else {
Ok(number.sqrt())
}
}
fn main() {
let result = divide(9.0, 3.0).and_then(square_root);
match result {
Ok(value) => println!("Square root of division result: {}", value),
Err(e) => println!("Error: {}", e),
}
}
Using ? Operator for Propagation
The ? operator can be used to propagate errors. If a function call returns Err, the ? operator will return the error from the calling function. If it returns Ok, the value is unwrapped and returned.
fn read_number_from_file(file_path: &str) -> Result<f64, Box<dyn std::error::Error>> {
let content = std::fs::read_to_string(file_path)?;
let number: f64 = content.trim().parse()?;
Ok(number)
}
fn main() {
match read_number_from_file("number.txt") {
Ok(number) => println!("Number from file: {}", number),
Err(e) => println!("Error: {}", e),
}
}
Summary
- Definition:
Resultis an enum that can beOk(T)for a success orErr(E)for a failure. - Creating: Functions can return
Resultto indicate success (Ok) or failure (Err). - Unwrapping: Use
unwrap,unwrap_or,unwrap_or_else, orunwrap_or_defaultto handleResult. - Chaining: Use
and_thenfor chaining operations that returnResult. - Error Propagation: Use the
?operator to propagate errors easily.
The Result type provides a robust and flexible way to handle errors in Rust, making error handling explicit and type-safe.