Rust does not use exceptions. Instead, it employs the Result<T, E>
type for handling recoverable errors and the panic!
macro to halt execution when an unrecoverable error occurs.
Key takeaways:
Result enum represents operations that can succeed or fail, with variants
Ok(T)
for success andErr(E)
for errors.Option enum is used to indicate the presence or absence of a value, with variants
Some(T)
for a value andNone
for no value.
Result
enables graceful error management, allowing functions to return errors without crashing the program.
Option
simplifies handling scenarios where a value might not exist, promoting safer code practices.Both enums enhance Rust's type safety by enforcing explicit handling of success and failure cases at compile time.
Rust is a modern systems programming language known for its focus on safety, performance, and concurrency. It features a powerful type system that prevents common programming errors at compile time, such as null pointer dereferences and data races.
Enums, one of Rust's key language constructs, allow developers to define custom types with a fixed set of possible values, making code more expressive and type-safe. Let's explore enums in Rust and how they enhance the language's expressiveness and safety.
We can create enums of our own, but Rust offers the following enums that are built into the language that we can make use of. They are as follows:
The Result
enum
The Option
enum
Let's explore in detail the functionality of the two.
Result
enumThe Result
enum is used for functions that can return either a successful value or an error. Result
is commonly used for operations that can fail, such as file I/O, network requests, or any operation that may result in an error. It has two variants:
The Ok
variant: This variant is used to denote the successful execution of code and is also returned in such cases.
The Err
variant: This variant is used for error handling and is used to return errors instead of halting program execution.
For example we can have a function return two different types of variables by using the Result
enum. Let's consider a scenario where we want a function to return an error if the value of a variable passed in it is less than five.
Otherwise, it will return the same number.
fn return_result(number: i32) -> Result<i32, String>{if number >= 5 {Ok(number)} else {Err("Number is less than five!".to_string())}}fn main(){let x: i32 = 1;match return_result(x) {Ok(result) => println!("{}", result),Err (e) => println!("{}", e)}}
In the code shown above, we've created two functions:
Lines 1–7: This is the function in which we'll use the Result
enum to return two different types of variables.
Line 1: Let's talk about the function signature first. It takes in an unsigned integer and returns a Result
with the following two generics:
i32
String
Lines 2–6: This if
condition checks if the number is less than or greater than five and returns the Result
enum's variants accordingly.
Line 3: If the number is greater than or equal to five, then the return_result()
function returns the number wrapped in the Ok
variant.
Line 5: If the number is less than five, then the return_result()
function returns a String
.
Lines 10–17: This is our main()
function will get executed when we run the program.
Line 11: Here, we declare the variable that we'll pass into the function.
Lines 13–16: This is the match
statement which handles the different kinds of values returned by the return_result()
function.
Note: The
Result
enum is usually better in cases when the function has to return either it's intended value or an error. This allows us to catch errors without stopping program execution.
Option
enumOption
is commonly used in situations where a value may or may not be present. For example, when searching for an item in a collection. The Option
enum has two variants:
The Some
variant contains a value of type T
.
The None
variant indicates the absence of a value.
This enum is used to handle cases where there is no value present. Let's consider the same scenario for this enum as well. We'll use this inside a function that will either return a variable of a certain type, or return the variant of type.
fn return_option(number: i32) -> Option<i32> {if number >= 5 {Some(number)} else {None}}fn main(){let x: i32 = 5;match return_option(x) {Some(option) => println!("{}", option),None => println!("None!")}}
Let's take a look at the code shown above:
Lines 1–7: This is the return_option()
function that we'll use to return the Option
enum.
Lines 2–7: This if
block checks if the number being passed into the function is less than or equal to five.
Line 3: If it is greater than or equal to five, the function will return number
wrapped into the Some
variant of the enum.
Line 5: If it is less than five, the function will return a None
object which has no type.
Lines 10–17: This is our main()
function that gets called when we execute the code.
Line 11: This is the variable we'll use to test out the return_option()
function.
Lines 13–16: This match
statement handles the variants returned by the return_option()
function.
Note: We can use the
Option
enum for error handling as well. The absence of value simple makes us handle the specific case where the expected value was not returned.
Key differences |
|
|
Purpose | Represents success or error | Represents optionality |
Variants |
|
|
Error handling | No error information | Contains error type |
Enums represent a powerful language construct in Rust, enabling developers to define custom types with fixed sets of possible values.
By exploring built-in enums like Result
and Option
, developers can handle errors and represent absence or presence of values effectively. These language features contribute to Rust's expressiveness, safety, and suitability for building robust and scalable systems.
Haven’t found what you were looking for? Contact Us
Free Resources