Options in Rust
Tags: rust, option
Published: 2023-01-24 10:43:09

In this blog post, we're going to see how to work with Options in Rust

##### Options

Since Rust doesn't support Nulls instead it has Optional value. Option is an Enum type which has 2 variants such as `Some` and `None`

##### Use cases

Following are some of the use cases with Option in Rust

Variable Initiation
Function return values
Return values for otherwise reporting simple errors
Optional struct fields
Optional functional arguments

##### Variable Initiation

```rust
    // Declaring variable with None
    let a: Option<i32> = None;

    // Declaring variable with Some(100)
    let b: Option<i32> = Some(100);
```

##### Extracting Values from Option

Extracting values from Option can be done using various ways

###### if-let statement

```rust
    if let Some(x) = a {
        println!("Value of variable a => {x}");
    }
```

###### match expression

```rust
    match b {
        Some(x) => println!("Value of variable b => {x}"),
        None => println!("Value of variable b => None"),
    }
```

###### expect method

`expect` method panics with a provided custom message when the variable is of `None` variant

```rust
    println!("Value of variable a => {}", b.expect("Variable cannot be empty"));
```

###### unwrap method

`unwrap` method panics with a generic message when the variable is of `None` variant

```rust
    println!("Value of variable a => {}", b.unwrap());
```

###### unwrap_or method

`unwrap_or` method returns value of variable OR specified value

```rust
    println!("Value of variable a => {}", a.unwrap_or(0));
```

###### unwrap_or_default method

`unwrap_or_default` method returns value of variable OR default value of underlying type

```rust
    println!("Value of variable a => {}", a.unwrap_or_default());
```

###### unwrap_or_else method

`unwrap_or_else` method returns value of variable OR returns the value of the function argument

```rust
    println!("Value of variable a => {}", a.unwrap_or_else(|| 10));
```

##### Comparing Option Variables

It is possible to compare 2 option variables in Rust

```rust
    if a > b {
        println!("Variable value a is greater than value of variable b");
    } else {
        println!("Variable value a is less than value of variable b");
    }
```

##### Iterating over Option

An `Option` can be iterated over. It is possible to call `FromIterator` trait's method on an Option. In case if an `Option` array contains `None`, the resulted operation would be `None` as well. 

In this below example, we're creating an Option array having mixed of `Some` and `None` variants

```rust
  let o_arr = [Some(10), Some(20), None, Some(30)];
```

###### Collecting elements from an Option array

We'll apply `FromIterator` trait's `into_iter` method and call `collect` method on it. This will result in `None` variant

```rust
    let result_1: Option<Vec<i32>> = o_arr.into_iter().collect();
    println!("Collect the elements => {result_1:?}");
```

###### Filter Option array and collect elements

We'll apply `FromIterator` trait's `filter` method and call `collect` method on it. This time, the result will be `Some<Vec<i32>>`

```rust
    let result_2: Option<Vec<i32>> = o_arr.into_iter().filter(|x| x.is_some()).collect();
    println!("Filter & collect the elements => {result_2:?}");
```

###### Sum method on an Option array

We'll apply `FromIterator` trait's `sum` method and as it is having `None` variant, the result will be of `None` variant

```rust
    let result_3: Option<i32> = o_arr.into_iter().sum();
    println!("Sum of all elements without filter => {result_3:?}");
```

###### Product method on an Option array

We'll apply `FromIterator` trait's `product` method and as it is having `None` variant, the result will be of `None` variant

```rust
    let result_4: Option<i32> = o_arr.into_iter().product();
    println!("Product of all elements without filter => {result_4:?}");
```

###### Filter & Sum method on an Option array

Filter the option array and then call `FromIterator` trait's `sum` method. The result will be of `Some<i32>` variant

```rust
    let result_3: Option<i32> = o_arr.into_iter().filter(|x| x.is_some()).sum();
    println!("Sum of all elements after filter => {result_3:?}");
```

###### Filter & Product method on an Option array

Filter the option array and then call `FromIterator` trait's `product` method. The result will be of `Some<i32>` variant

```rust
    let result_4: Option<i32> = o_arr.into_iter().filter(|x| x.is_some()).product();
    println!("Product of all elements after filter => {result_4:?}");
```

I hope this blog post gives you a brief overview about Options.

All the code examples can be found in this [link](https://github.com/sivakumar-sivaprakasam/rust-examples/tree/main/options).

Please feel free to share your feedback.

Happy reading!!!