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:
Result
is an enum that can beOk(T)
for a success orErr(E)
for a failure. - Creating: Functions can return
Result
to indicate success (Ok
) or failure (Err
). - Unwrapping: Use
unwrap
,unwrap_or
,unwrap_or_else
, orunwrap_or_default
to handleResult
. - Chaining: Use
and_then
for 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.