Option Enum in Rust

Option Enum used to represent a value that can be either present(Some(T)) or absent(None)

Option<T> Enum has two Variants.

 
    Option<T>{
        None, 
        Some(T)
    }
    

where, Some(T) -> Used to represent value(T is a generic type here - It can be any type) None -> Used when the value is absent

Here's the simple example of using Option Enum.


    struct User {
        full_name: String, 
        nickname: Option<String>
    }


    impl User {
        fn get_user_nickname(&self) -> String {
           match &self.nickname {
               Some(nickname) => nickname.clone(), 
               None => "doesn't have a nick name".to_string()
           } 
        }
    }


    fn main() {
        let michael = User {
            full_name: "Michael".to_string(), 
            nickname: Some("Mike".to_string())
        };

        println!("Michael nick name is {} ",michael.get_user_nickname());
        
        let john = User {
            full_name: "John".to_string(), 
            nickname: None, 
        };
        
        println!("John {}", john.get_user_nickname());
    }

Here, I defined the nickname field in User struct as a Option Enum. So, nickname field can be None, in such cases where a user don't have a nick name.

Then, I use Some and None variants of Option Enum for nickname field according to the need, when I declare the User struct, and the output.

    Michael nickname is Mike 
    John doesn't have a nickname

So, We can use Option Enum where we unsure whether the value present or not(null).

Impl Methods

Option Enum has several impl methods, It helps to work with Option Enum. Here, We will see some common methods.

is_some and is_none

We can use is_some and is_none methods to check whether our option variable contains value or not. Let's consider below example,


  fn main() {
      let number: Option<i32> = Some(43);
      
      println!("{}", number.is_some()); // true
      
      let number: Option<i32> = None; 
      
      println!("{}",  number.is_none()); // true
  }

is_some method will return true if our option variable contains a value.

Likewise, is_none method will return true if our option variable contains a absence of a value.

as_ref

as_ref method gives access to reference of the Option type. For example,


    let name: Option<String> = Some(String::from("John"));
        
    let ref_name: Option<&String> = name.as_ref();

Here, as_ref method converts Option<T> type to Option<&T> .

We can use as_ref() when we only need to borrow the value of Option variable instead of taking ownership of it.

unwrap

unwrap() is used to retrieve the Some(value) value from the Option Type. unwrap will panic if we use againt `None` value


    let number = Some(32);
    
    println!("{:?}", number); // Some(32)

    let number = number.unwrap();
    
    println!("{}", number); // 32
    
        
    let not_number: Option<i32> = None;
    
    let not_number = not_number.unwrap();   // It will panic
    

Be sure to with unwrap, as it will panic if the Option is None. It's recommended to use it only when you're sure that the Option will contain a value.

unwrap_or_else

In, unwrap_or_else, If option has value it will return the value. If Option is None, it will call the closure.


    let number: Option<i32> = None;
    
    println!("number {:?}", number); // number None
    
    let number = number.unwrap_or_else(|| 5);
    
    println!("number {}", number); // number 5

Here, We defined the None variant. So, unwrap_or_else closure will be called and return the value

Conclusion

I hope you learned something new from this article. If you want to check, here is the full documentation of option enum.