# If

* `if` is an expression.
* All `if` expressions start with the keyword `if`, followed by a condition.
* It’s also worth noting that the condition in this code must be a `bool`. If the condition isn’t a `bool`, we’ll get an error.
* Because `if` is an expression, we can use it on the right side of a `let` statement to assign the outcome to a variable
* Reference: [Control Flow](https://doc.rust-lang.org/book/ch03-05-control-flow.html#if-expressions)

## if1.rs

```rust
fn bigger(a: i32, b: i32) -> i32 {
    // fill the function body using if expression
    if a > b {
        a
    } else {
        b
    }
}

fn main() {
    // You can optionally experiment here.
}

// Don't mind this for now :)
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn ten_is_bigger_than_eight() {
        assert_eq!(10, bigger(10, 8));
    }

    #[test]
    fn fortytwo_is_bigger_than_thirtytwo() {
        assert_eq!(42, bigger(32, 42));
    }

    #[test]
    fn equal_numbers() {
        assert_eq!(42, bigger(42, 42));
    }
}
```

* This exercise is simple, we just need to add `if` expression that checks which variable is bigger in the function `bigger`.

  ```rust
  if a > b {
    a
  } else {
    b
  }
  ```
* Because `if` is an expression we can just type `a` and `b` and it will serve as returned value.

## if2.rs

```rust
// TODO: Fix the compiler error on this function.
fn picky_eater(food: &str) -> &str {
    if food == "strawberry" {
        "Yummy!"
    } else if food == "potato" { // if potato return "I guess I can eat that."
        "I guess I can eat that."
    } else { // else return "No thanks!"
        "No thanks!"
    }
}

fn main() {
    // You can optionally experiment here.
}

// TODO: Read the tests to understand the desired behavior.
// Make all tests pass without changing them.
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn yummy_food() {
        // This means that calling `picky_eater` with the argument "food" should return "Yummy!".
        assert_eq!(picky_eater("strawberry"), "Yummy!");
    }

    #[test]
    fn neutral_food() {
        assert_eq!(picky_eater("potato"), "I guess I can eat that.");
    }

    #[test]
    fn default_disliked_food() {
        assert_eq!(picky_eater("broccoli"), "No thanks!");
        assert_eq!(picky_eater("gummy bears"), "No thanks!");
        assert_eq!(picky_eater("literally anything"), "No thanks!");
    }
}
```

* In this example we need to take a look at the predefined testcases.
  * Test1 - `yummy_food`: : expect string `"Yummy!"` if the argument is `"strawberry"`.
  * Test2 - `neutral_food`: expect string `"I guess I can eat that."` if the argument is `"potato"`.
  * Test3 - `default_disliked_food`: expect string `"broccoli"`, `"gummy bears"`, or `"literally anything"`.
* We are missing two case in the `picky_eater` function.
* So lets add `potato` using `else if` and the rest can go to `else` block.

## if3.rs

```rust
fn animal_habitat(animal: &str) -> &str {
    // Make sure all returned values have the same types
    let identifier = if animal == "crab" {
        1
    } else if animal == "gopher" {
        2 // Don't return float
    } else if animal == "snake" {
        3
    } else {
        0 // Use 0 as substitute of unknown values
    };

    // Don't change the expression below!
    if identifier == 1 {
        "Beach"
    } else if identifier == 2 {
        "Burrow"
    } else if identifier == 3 {
        "Desert"
    } else {
        "Unknown"
    }
}

fn main() {
    // You can optionally experiment here.
}

// Don't change the tests!
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn gopher_lives_in_burrow() {
        assert_eq!(animal_habitat("gopher"), "Burrow")
    }

    #[test]
    fn snake_lives_in_desert() {
        assert_eq!(animal_habitat("snake"), "Desert")
    }

    #[test]
    fn crab_lives_on_beach() {
        assert_eq!(animal_habitat("crab"), "Beach")
    }

    #[test]
    fn unknown_animal() {
        assert_eq!(animal_habitat("dinosaur"), "Unknown")
    }
}
```

* Because `if` is an expression, we can use it on the right side of a `let` statement to assign the outcome to a variable
* In this case we just need make sure that the returned values in the `identifier` if expression to have the same types.
* Make `0` as substitute of `"unknown"` value.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bagus-cahyono.gitbook.io/programming-notes/rust/rustlings_exercise/03_if.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
