Result type in Rust
Tags: rust, result
Published: 2023-01-24 13:15:53

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

##### Result

Result is a type used for returning and propagating errors in Rust. It is an Enum type which has 2 variants such as `Ok' and `Err'. `Ok` represents success and containing value and `Err` representing error and containing an error value

##### Variable Initiation

```rust
    // Declaring variable with Ok() variant of Result type
    let a: Result<i32, &str> = Ok(100);

    // Declaring variable with Err() variant of Result type
    let b: Result<i32, &str> = Err("Invalid input provided");
```

##### Extracting Values from Result

Extracting values from Result can be done using various ways

###### if-let statement

```rust
    // Get value of Result type's Ok() variant
    if let Ok(x) = a {
        println!("Extracted value from 'a' is => {x}");
    }

    // Get value of Result type's Err() variant
    if let Err(x) = b {
        println!("Extracted value from 'b' is => {x}");
    }
```

###### match expression

```rust
    match a {
        Ok(x) => println!("Extracted Ok() variant's value from 'a' is => {x}"),
        Err(x) => println!("Extracted Err() variant's value from 'a' is => {x}"),
    }

    match b {
        Ok(x) => println!("Extracted Ok() variant's value from 'b' is => {x}"),
        Err(x) => println!("Extracted Err() variant's value from 'b' is => {x}"),
    }
```

###### expect method

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

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

###### unwrap method

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

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

###### unwrap_or method

`unwrap_or` method returns value of Ok() variant OR specified value

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

###### unwrap_or_default method

`unwrap_or_default` method returns value of Ok() variant 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 Ok() variant OR returns the value of the function argument

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

###### expect_err method

`expect_err` method panics with a provided custom message

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

###### unwrap_err method

`unwrap_err` method panics with a generic message

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

##### Comparing Result Variables

It is possible to compare 2 Result 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 Result

A `Result` can be iterated over. It is possible to call `FromIterator` trait's method on a Result. In case if a `Result` array contains `Err`, the resulted operation would be `Err` as well. 

In this below example, we're creating a Result array having mixed of `Ok` and `Err` variants

```rust
    let r_arr = [Ok(10), Ok(20), Err("Invalid user input"), Ok(30)];
```

###### Collecting elements from Result array

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

```rust
    let result_1: Result<Vec<i32>, &str> = r_arr.into_iter().collect();
    println!("Collect the elements => {result_1:?}");
```

###### Filter Result array and collect elements

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

```rust
    let result_2: Result<Vec<i32>, &str> = r_arr.into_iter().filter(|x| x.is_ok()).collect();
    println!("Filter & collect the elements => {result_2:?}");
```

###### Sum method on Result array

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

```rust
    let result_3: Result<i32, &str> = r_arr.into_iter().sum();
    println!("Sum of all elements without filter => {result_3:?}");
```

###### Product method on Result array

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

```rust
    let result_4: Result<i32, &str> = r_arr.into_iter().product();
    println!("Product of all elements without filter => {result_4:?}");
```

###### Filter & Sum method on Result array

Filter the option array and then call `FromIterator` trait's `sum` method. The result will be of `Result<i32, &str>` type

```rust
    let result_3: Result<i32, &str> = r_arr.into_iter().filter(|x| x.is_ok()).sum();
    println!("Sum of all elements after filter => {result_3:?}");
```

###### Filter & Product method on Result array

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

```rust
    let result_4: Result<i32, &str> = r_arr.into_iter().filter(|x| x.is_ok()).product();
    println!("Product of all elements after filter => {result_4:?}");
```

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

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

Please feel free to share your feedback.

Happy reading!!!