Skip to content

Instantly share code, notes, and snippets.

@wrongbyte
Created December 8, 2022 12:50

Revisions

  1. wrongbyte created this gist Dec 8, 2022.
    40 changes: 40 additions & 0 deletions question.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,40 @@
    On the function below, we have a function that returns a `bool` wrapped by a `Result`.
    We want to use the bool that is inside of this function, but we don't want to use things like a if let, for example.
    How could we do this?
    ![image](https://user-images.githubusercontent.com/57643375/206446007-27c6c572-76b7-463e-b0c1-77157fd5aa3a.png)

    We can't do it, because we can't apply an unary operator to a `Result<bool>` - we have to first _unwrap_ the bool inside the `Result`.
    ![image](https://user-images.githubusercontent.com/57643375/206446350-50e4f819-91aa-4f56-ac7a-b06fd484429b.png)

    However, there's a lean solution to it: the **question mark operator**.

    ![image](https://user-images.githubusercontent.com/57643375/206446445-2b549a86-49a8-4518-baf6-7b747fbc6070.png)

    ### How does it work under the hood?
    We want to **evaluate** the return of `self.user_intention()`. That's what we do when we use the `!` combined with the `if` keyword. It's a shortcut for evaluating a bool variable assigned to the return of this function.

    However, as this function can return an `Err` - since its type is a `Result<bool, TerminalError>` - we have to deal with the failing case as well.
    We want to do so by using a _bubble up_, which is: _propagate the error to a higher level by returning it_.
    Then, we have two cases: **the success case, in which we _evaluate_ the value inside of the _Ok_ variant**, and the **failure case, in which we _return_ the error.**

    ### _Returning_ vs _evaluating_
    There's a very important detail here: _returning_ vs _evaluating_.
    Let's look it in detail.
    When a match returns the same type on all branches, it works as an **expression**; for example:
    ```rust
    let num_name = match num {
    0 => "zero",
    1 => "um",
    2 => "dois",
    _ => "outro",
    };
    ```
    _**But what happens if one of the branches uses the keyword `return`?**_
    Basically, the returned value **won't be assigned to the variable `num_name`.** It happens because the `return` keyword "stops" the flow once it is executed. So, we will return from the function - and here it is our opportunity to apply the bubble up!

    ### Summary
    The behavior described above can be written as a `match`, as it follows:
    ![image](https://user-images.githubusercontent.com/57643375/206450918-b6976ed4-4592-4f7c-9c4e-ad47a6de2bb8.png)