Nice Features: Option
Instead of nil
, None
, or Null
, in Rust we have the Option
enum type.
#![allow(unused_variables)] fn main() { enum Option<T> { Some(T), None, } }
An example of how we are using an Option
type in our app code.
#![allow(unused_variables)] fn main() { /// A GIF from the Giphy API which has been saved by a user. struct SavedGif { /// Object ID. pub id: i64, /// The ID of the user which has saved this GIF. pub user: i64, /// The ID of this GIF in the Giphy system. pub giphy_id: String, /// The title of the GIF. pub title: String, /// The URL of the GIF. pub url: String, /// The category given to this GIF by the user. pub category: Option<String>, } }
How might we use this?
#![allow(unused_variables)] fn main() { // Take the inner value, or a default. gif.category.unwrap_or_default(); // Take the inner value, or an explicit alternative. gif.category.unwrap_or(String::from("Woo!")); gif.category.unwrap_or_else(|| String::from("Woo!")); // Using a closure. // Match on the structure of the option itself. // This matches against the possible variants of the type. match gif.category { Some(val) => val, None => String::from("New Val"), } // If we just want to check for Some(..) or None. if let Some(val) = gif.category { // Use the inner value here. } if let None = gif.category { // No category, so do something else. } }
Why is this great? No more nil pointer dereferencing.
What about our own custom enum types? Here is one that we use heavily in the app.
#![allow(unused_variables)] fn main() { /// An API response. enum Response<D> { /// A success payload with data. Data(D), /// An error payload with an error. Error(Error), } }