Comment on page
The Option struct
Consider that you want to implement a function that returns a username, given the corresponding user identifier. The signature of the function could be as follows:
fn get_username_by_id(id: u32) -> String {
// function body
}
In a success case, you pass the user identifier as a parameter and the function returns the corresponding username. However, what happens if the function does not have a username for the given identifier? A possible solution is to return an empty string:
- If the function is able to retrieve the data, then the string returned is the username.
- If the function is NOT able to retrieve the data, then the string returned is the empty string (
''
).
Although this is a valid approach, it creates hidden logic that is not visible unless you deep dive into the function code.
Rust provides a better way of dealing with these situations by using the
Option<T>
enum. This enum has two possible values: Some(T)
(used when the returned value is present) and None
(used when the returned value is not present). Therefore, the previous function can be refactored to:fn get_username_by_id(id: u32) -> Option<String> {
// function body
}
Now, the function works as follows:
- If the function is able to retrieve the data, then a
Some
value containing the string is returned. - If the function is NOT able to retrieve the data, then a
None
value is returned.
Let's complete the body of the function:
fn get_username_by_id(id: u32) -> Option<String> { // 1.
match(id) {
1 => Some(String::from("Susan")), // 2.
2 => Some(String::from("John")), // 3.
_ => None // 4.
}
}
- 1.Given a user identifier, return the corresponding username if it exists.
- 2.If
id == 1
, then aSome
struct containing the string is returned. - 3.If
id == 2
, then aSome
struct containing the string is returned. - 4.If
id
does not match with any of the provided identifiers, then aNone
struct is returned.
The
Option<T>
struct contains two helper methods to check if the returned type is Some
or None
: the .is_some()
and .is_none()
methods. Let's see how to use these methods:fn get_username_by_id(id: u32) -> Option<String> {
match(id) {
1 => Some(String::from("Susan")),
2 => Some(String::from("John")),
_ => None
}
}
fn main() {
let user1 = get_username_by_id(1); // 1.
let user10 = get_username_by_id(10); // 2.
if (user1.is_some()) { // 3.
println!("User with id = 1 holds username {}", user1.unwrap())
}
if (user10.is_none()) { // 4.
println!("User with id = 10 does not exist")
}
}
- 1.Get the user with
id == 1
. - 2.Get the user with
id == 10
. - 3.If the function returned a name for
id == 1
, thenuser1.is_some()
returnstrue
. - 4.If the function did NOT return a name for
id == 10
, thenuser1.is_none()
returnstrue
.
fn get_username_by_id(id: u32) -> Option<String> {
match(id) {
1 => Some(String::from("Susan")),
2 => Some(String::from("John")),
_ => None
}
}
fn main() {
let user1 = get_username_by_id(1);
let user10 = get_username_by_id(10);
match (&user1) {
Some(name) => println!("User with id = 1 holds username {}", &user1.unwrap()),
None => println!("No user with id = 1 found")
}
match (&user10) {
Some(name) => println!("User with id = 10 holds username {}", &user10.unwrap()),
None => println!("No user with id = 10 found")
}
}
Last modified 2mo ago