## Control flow

See this chapter on YouTube: Part 1 and Part 2

Control flow means telling your code what to do in different situations. The simplest control flow is `if`.

``````fn main() {
let my_number = 5;
if my_number == 7 {
println!("It's seven");
}
}
``````

Also note that you use `==` and not `=`. `==` is to compare, `=` is to assign (to give a value). Also note that we wrote `if my_number == 7` and not `if (my_number == 7)`. You don't need brackets with `if` in Rust.

`else if` and `else` give you more control:

``````fn main() {
let my_number = 5;
if my_number == 7 {
println!("It's seven");
} else if my_number == 6 {
println!("It's six")
} else {
println!("It's a different number")
}
}
``````

This prints `It's a different number` because it's not equal to 7 or 6.

You can add more conditions with `&&` (and) and `||` (or).

``````fn main() {
let my_number = 5;
if my_number % 2 == 1 && my_number > 0 { // % 2 means the number that remains after diving by two
println!("It's a positive odd number");
} else if my_number == 6 {
println!("It's six")
} else {
println!("It's a different number")
}
}
``````

This prints `It's a positive odd number` because when you divide it by 2 you have a remainder of 1, and it's greater than 0.

You can see that too much `if`, `else`, and `else if` can be difficult to read. In this case you can use `match` instead, which looks much cleaner. But you must match for every possible result. For example, this will not work:

``````fn main() {
let my_number: u8 = 5;
match my_number {
0 => println!("it's zero"),
1 => println!("it's one"),
2 => println!("it's two"),
// ⚠️
}
}
``````

The compiler says:

``````error[E0004]: non-exhaustive patterns: `3u8..=std::u8::MAX` not covered
--> src\main.rs:3:11
|
3 |     match my_number {
|           ^^^^^^^^^ pattern `3u8..=std::u8::MAX` not covered
``````

This means "you told me about 0 to 2, but `u8`s can go up to 255. What about 3? What about 4? What about 5?" And so on. So you can add `_` which means "anything else".

``````fn main() {
let my_number: u8 = 5;
match my_number {
0 => println!("it's zero"),
1 => println!("it's one"),
2 => println!("it's two"),
_ => println!("It's some other number"),
}
}
``````

That prints `It's some other number`.

Remember this for match:

• You write `match` and then make a `{}` code block.
• Write the pattern on the left and use a `=>` fat arrow to say what to do when it matches.
• Each line is called an "arm".
• Put a comma between the arms (not a semicolon).

You can declare a value with a match:

``````fn main() {
let my_number = 5;
let second_number = match my_number {
0 => 0,
5 => 10,
_ => 2,
};
}
``````

`second_number` will be 10. Do you see the semicolon at the end? That is because, after the match is over, we actually told the compiler this: `let second_number = 10;`

You can match on more complicated things too. You use a tuple to do it.

``````fn main() {
let sky = "cloudy";
let temperature = "warm";

match (sky, temperature) {
("cloudy", "cold") => println!("It's dark and unpleasant today"),
("clear", "warm") => println!("It's a nice day"),
("cloudy", "warm") => println!("It's dark but not bad"),
_ => println!("Not sure what the weather is."),
}
}
``````

This prints `It's dark but not bad` because it matches "cloudy" and "warm" for `sky` and `temperature`.

You can even put `if` inside of `match`. This is called a "match guard":

``````fn main() {
let children = 5;
let married = true;

match (children, married) {
(children, married) if married == false => println!("Not married with {} children", children),
(children, married) if children == 0 && married == true => println!("Married but no children"),
_ => println!("Married? {}. Number of children: {}.", married, children),
}
}
``````

This will print `Married? true. Number of children: 5.`

You can use _ as many times as you want in a match. In this match on colours, we have three but only check one at a time.

``````fn match_colours(rbg: (i32, i32, i32)) {
match rbg {
(r, _, _) if r < 10 => println!("Not much red"),
(_, b, _) if b < 10 => println!("Not much blue"),
(_, _, g) if g < 10 => println!("Not much green"),
_ => println!("Each colour has at least 10"),
}
}

fn main() {
let first = (200, 0, 0);
let second = (50, 50, 50);
let third = (200, 50, 0);

match_colours(first);
match_colours(second);
match_colours(third);

}
``````

This prints:

``````Not much blue
Each colour has at least 10
Not much green
``````

This also shows how `match` statements work, because in the first example it only printed `Not much blue`. But `first` also has not much green. A `match` statement always stops when it finds a match, and doesn't check the rest. This is a good example of code that compiles well but is not the code you want.

You can make a really big `match` statement to fix it, but it is probably better to use a `for` loop. We will talk about loops soon.

A match has to return the same type. So you can't do this:

``````fn main() {
let my_number = 10;
let some_variable = match my_number {
10 => 8,
_ => "Not ten", // ⚠️
};
}
``````

The compiler tells you that:

``````error[E0308]: `match` arms have incompatible types
--> src\main.rs:17:14
|
15 |       let some_variable = match my_number {
|  _________________________-
16 | |         10 => 8,
| |               - this is found to be of type `{integer}`
17 | |         _ => "Not ten",
| |              ^^^^^^^^^ expected integer, found `&str`
18 | |     };
| |_____- `match` arms have incompatible types
``````

This will also not work, for the same reason:

``````fn main() {
let some_variable = if my_number == 10 { 8 } else { "something else "}; // ⚠️
}
``````

But this works, because it's not a `match` so you have a different `let` statement each time:

``````fn main() {
let my_number = 10;

if my_number == 10 {
let some_variable = 8;
} else {
let some_variable = "Something else";
}
}
``````

You can also use `@` to give a name to the value of a `match` expression, and then you can use it. In this example we match an `i32` input in a function. If it's 4 or 13 we want to use that number in a `println!` statement. Otherwise, we don't need to use it.

``````fn match_number(input: i32) {
match input {
number @ 4 => println!("{} is an unlucky number in China (sounds close to 死)!", number),
number @ 13 => println!("{} is unlucky in North America, lucky in Italy! In bocca al lupo!", number),
_ => println!("Looks like a normal number"),
}
}

fn main() {
match_number(50);
match_number(13);
match_number(4);
}
``````

This prints:

``````Looks like a normal number
13 is unlucky in North America, lucky in Italy! In bocca al lupo!
4 is an unlucky number in China (sounds close to 死)!
``````