16 Some()
or None
?
Understand how missingness is handled in Rust with Option<T>
. - Understand how to handle missingness - Use Option<T>
in an applied case
Rust doesn’t have the concept of a NULL
type. Null values are quite dangerous and have their own category of errors and security issues.
Rust makes it impossible to have a null value by formalizing the concept of missingness through the Option<>
Option
An Option is a special enum
that has two possible values:
enum Option {
Some(T),
None
}
When a value is missing, the option’s variant is None
. When the option contains some value, the value is contained inside of the Some(T)
variant.
Accessing Some()
value
Since Option<T>
are “just” an enum, we can match on the variants to access the values.
// create an Option<Measure> that contains a value
let measure = Some(Measure::Euclidean);
match measure {
Some(v) => println!("The measure is not missing!"),
None => println!("Oh no! The measure is missing"),
}
We put a placeholder value inside of Some(v)
to create a binding to the inner value. It’s like a function argument, it can be called whatever you want it to be.
Danger! .unwrap()
& .expect()
Sometimes dealing with options is a headache, particularly when we’re in the early stages of developing.
We can use .unwrap()
or .expect()
to grab the inner value of an option without matching.
This is dangerous!! because we are ignoring the possibility of a None
. Unwrapping on a None
leads to a panic. Panics cause your program to abort.
'main' panicked at src/main.rs:4:41:
thread Option::unwrap()` on a `None` value called `
Exercise
- Modify the
distance()
method to take anOption<&Measure>
- When
None
use euclidean distance, otherwise use the provided distance measure
The exercise does not involve .unwrap()
because it’s a bad habbit. Let’s try and form good habbits from the outset if possible.
View solution
impl Point {
fn distance(&self, destination: &Self, measure: Option<&Measure>) -> f64 {
match measure {
Some(m) => match m {
Measure::Euclidean => self.euclidean_distance(destination),
Measure::Haversine => self.haversine_distance(destination),
},
None => self.euclidean_distance(destination),
}
}
}