1
00:00:02,270 --> 00:00:09,619
Control flow features let you write code that takes one action in some situations and another action in different situations. They're how you express decisions in your code.
2
00:00:09,620 --> 00:00:28,020
In this module, we're going to cover if, else if, and else; three different kinds of loops - loop, while, and for; and the match expression. We'll be defining and calling functions in this module,
3
00:00:28,240 --> 00:00:30,260
so check out the previous module on functions
4
00:00:30,270 --> 00:00:31,170
if you need to review.
5
00:00:32,740 --> 00:00:48,950
Let's start with if, else if, and else. We can write code that only uses if by starting with the if keyword, then an expression that evaluates to a Boolean, then curly brackets containing the code that should run if the condition evaluates to true.
6
00:00:49,840 --> 00:00:51,640
If the condition evaluates to false,
7
00:00:51,720 --> 00:00:55,820
the code in the brackets won't get run.
8
00:00:55,880 --> 00:01:00,210
Optionally, you can have an else block that goes with an if block that contains code to run,
9
00:01:00,220 --> 00:01:02,050
if the condition evaluates to false.
10
00:01:04,140 --> 00:01:08,469
You can also have multiple conditions by having an if block, then an else if
11
00:01:08,470 --> 00:01:10,050
block with another condition,
12
00:01:10,540 --> 00:01:12,250
as many else if blocks as you want,
13
00:01:13,240 --> 00:01:15,300
and then an optional else block that is run
14
00:01:15,310 --> 00:01:20,540
if all of the conditions evaluate to false.
15
00:01:20,630 --> 00:01:26,550
Like with functions, we can get a value from an if or else block by leaving the semicolon off of the last expression in the block.
16
00:01:27,540 --> 00:01:29,450
We can then put that value in a variable.
17
00:01:30,240 --> 00:01:30,499
Note,
18
00:01:30,500 --> 00:01:33,350
we do need a semicolon to end the variable assignment statement.
19
00:01:34,940 --> 00:01:35,920
This code prints
20
00:01:36,070 --> 00:01:37,650
Your discount is 50!.
21
00:01:39,980 --> 00:01:44,150
Note that when we return a value from an if else expression for a variable,
22
00:01:44,740 --> 00:01:51,350
there must be an else clause so that the variable always gets a value. And the types of the values must all be the same -
23
00:01:51,740 --> 00:01:52,450
in this case,
24
00:01:52,530 --> 00:01:53,250
i32.
25
00:01:55,540 --> 00:01:56,120
Next,
26
00:01:56,250 --> 00:01:57,250
let's talk about loops.
27
00:01:59,040 --> 00:02:01,220
Loops let you run the same code repeatedly.
28
00:02:02,670 --> 00:02:06,750
The loop keyword lets you specify a block of code that should be run forever.
29
00:02:07,640 --> 00:02:09,210
This loop prints hello, world!
30
00:02:09,220 --> 00:02:10,250
over and over again.
31
00:02:12,140 --> 00:02:14,350
This program will run until the end of time.
32
00:02:14,940 --> 00:02:16,139
We've stopped it using Ctrl + C.
33
00:02:18,240 --> 00:02:20,550
You can use the break keyword to exit a loop.
34
00:02:21,940 --> 00:02:23,560
This code will loop forever,
35
00:02:23,850 --> 00:02:25,850
asking What's the secret word?
36
00:02:26,340 --> 00:02:29,970
and waiting for input, unless you type in the correct secret word, rust. In that case, we'll break out of the loop.
37
00:02:30,010 --> 00:02:40,550
When we run this program and type java, the loop asks us again,
38
00:02:41,080 --> 00:02:42,280
and if we type rust,
39
00:02:42,530 --> 00:02:44,950
the code breaks out of the loop and the program ends.
40
00:02:47,640 --> 00:02:48,719
The code we've written here,
41
00:02:48,720 --> 00:02:53,150
using loop, if, and break, could also be written using a while loop.
42
00:02:54,140 --> 00:03:01,870
A while loop is written with the while keyword, then an expression that evaluates to true or false, then curly brackets and a block of code.
43
00:03:03,140 --> 00:03:04,979
The code in the block runs over and over,
44
00:03:04,980 --> 00:03:06,990
while the expression specified is true.
45
00:03:09,040 --> 00:03:12,350
Here's the secret word example rewritten using a while loop.
46
00:03:13,140 --> 00:03:16,250
It works exactly the same, but is a little bit more concise.
47
00:03:17,740 --> 00:03:21,250
The condition for when the loop should exit is now part of the start of the loop,
48
00:03:21,740 --> 00:03:23,310
rather than inside the loop somewhere.
49
00:03:25,990 --> 00:03:28,950
The for loop is probably the most common loop in Rust code.
50
00:03:29,880 --> 00:03:32,650
It lets you run some code for each item in a collection.
51
00:03:33,870 --> 00:03:36,150
Unlike for loops in some other languages, like C,
52
00:03:36,840 --> 00:03:39,979
you don't need to manage an index into the collection and worry about
53
00:03:39,980 --> 00:03:44,950
off-by-one errors.
54
00:03:45,340 --> 00:03:46,450
To write a for loop, use the for keyword,
55
00:03:47,240 --> 00:03:56,750
then pick a variable name to use inside the loop body to refer to each individual item. Then, put the keyword in, and specify the collection you want to use.
56
00:03:57,640 --> 00:04:00,810
Then, put curly brackets and the code that should be run for each item.
57
00:04:03,540 --> 00:04:09,790
Here, for the collection, we're using the range syntax - two dots - to create a range of integers,
58
00:04:09,800 --> 00:04:15,450
starting from 1 inclusive and ending before 11.
59
00:04:15,940 --> 00:04:21,450
For each number in the range, the for loop will print Now serving number with the number of the current iteration through the loop.
60
00:04:22,440 --> 00:04:28,950
We can see that this code starts by printing Now serving number 1, and ends with printing Now serving number 10.
61
00:04:31,240 --> 00:04:31,810
Finally,
62
00:04:32,050 --> 00:04:33,750
let's talk about match expressions.
63
00:04:35,140 --> 00:04:38,050
match isn't something very many programming languages have.
64
00:04:38,840 --> 00:04:39,970
It's sort of like a bunch of
65
00:04:39,980 --> 00:04:42,920
if/else ifs and sort of like a switch
66
00:04:42,930 --> 00:04:43,169
or case
67
00:04:43,170 --> 00:04:43,750
statement,
68
00:04:44,340 --> 00:04:46,050
but better for two reasons:
69
00:04:46,540 --> 00:04:48,550
pattern matching and exhaustiveness checking.
70
00:04:50,140 --> 00:04:50,700
First,
71
00:04:50,870 --> 00:04:52,250
let's talk about pattern matching.
72
00:04:53,740 --> 00:04:57,050
Pattern matching is a feature available in Rust in multiple places.
73
00:04:57,940 --> 00:05:01,850
We actually used pattern matching when we destructured a tuple into parts
74
00:05:02,280 --> 00:05:03,550
in the Data types module. Surprise!
75
00:05:04,040 --> 00:05:09,750
Pattern matching is especially useful in match expressions.
76
00:05:10,440 --> 00:05:19,050
We specify a list of patterns to test a value against, and the match expression tests the value against each pattern and stops if it finds a matching one.
77
00:05:20,040 --> 00:05:21,980
Then, it runs the code that goes with that pattern.
78
00:05:24,740 --> 00:05:26,780
Here's an example of a match expression.
79
00:05:27,640 --> 00:05:29,850
We have an integer stored in the variable x,
80
00:05:30,340 --> 00:05:32,850
and we want to match x against some patterns.
81
00:05:33,640 --> 00:05:34,330
In this case,
82
00:05:34,340 --> 00:05:36,070
the patterns are literal numbers.
83
00:05:37,940 --> 00:05:40,210
What Rust does is it takes x,
84
00:05:40,400 --> 00:05:44,650
which in this case is 3, and compares it to 1, which doesn't match.
85
00:05:45,140 --> 00:05:46,810
So, it moves on to the next pattern,
86
00:05:46,870 --> 00:05:47,350
2,
87
00:05:47,740 --> 00:05:51,020
which also doesn't match, onto the next pattern,
88
00:05:51,030 --> 00:05:51,530
3,
89
00:05:51,810 --> 00:05:52,900
which does match.
90
00:05:53,140 --> 00:05:56,950
So, Rust will print, Three's a crowd, and be done with this match expression.
91
00:05:58,280 --> 00:06:06,340
The underscore in the last pattern is a catch-all that will match any value. So, the last arm functions like an else in a set of
92
00:06:06,350 --> 00:06:07,049
if/else
93
00:06:07,050 --> 00:06:08,250
if/else blocks.
94
00:06:10,040 --> 00:06:13,150
There are lots of different ideas you can express with pattern matching.
95
00:06:14,240 --> 00:06:19,050
This example shows some logic that might be used in a board game where you roll two dice.
96
00:06:19,640 --> 00:06:22,850
We've hardcoded the values of the dice roll to simplify this example.
97
00:06:23,340 --> 00:06:29,130
The first arm matches a role where both dice have the value 1. The second arm matches
98
00:06:29,140 --> 00:06:30,089
any role where
99
00:06:30,090 --> 00:06:31,340
one of the two dice is 5,
100
00:06:31,790 --> 00:06:37,450
but it doesn't matter which one, and we use underscores in the tuple pattern to ignore any other value.
101
00:06:38,880 --> 00:06:50,240
The vertical bar between the two patterns means or. Also, note that we can have multiple lines of code paired with the pattern by putting curly brackets around them.
102
00:06:50,250 --> 00:06:55,850
Again, the last pattern is an underscore that will match any value for the whole tuple that hasn't already been matched.
103
00:06:57,780 --> 00:06:58,650
This code prints,
104
00:06:59,040 --> 00:07:01,079
You rolled at least one 5! Move and
105
00:07:01,080 --> 00:07:01,880
then roll again!.
106
00:07:04,540 --> 00:07:10,050
The other reason match expressions are awesome is that they must be exhaustive and cover every case.
107
00:07:10,740 --> 00:07:14,350
This prevents bugs that can be caused by forgetting to handle a situation.
108
00:07:15,640 --> 00:07:16,350
For example,
109
00:07:16,840 --> 00:07:19,480
here's a match statement where we're checking two Booleans:
110
00:07:19,760 --> 00:07:21,540
is_confirmed and is_active.
111
00:07:22,440 --> 00:07:23,489
We've forgotten the case
112
00:07:23,490 --> 00:07:26,450
where is_confirmed is true and is_active is false.
113
00:07:28,640 --> 00:07:30,789
If we try to compile this, Rust
114
00:07:30,790 --> 00:07:34,900
can see that we haven't covered every possibility. In this case,
115
00:07:34,960 --> 00:07:37,150
it's even able to tell us which case we missed -
116
00:07:37,640 --> 00:07:37,949
thanks,
117
00:07:37,950 --> 00:07:38,350
Rust!
118
00:07:40,640 --> 00:07:52,780
We would fix this either by adding the explicit case we missed or by using an underscore to explicitly acknowledge that we want to ignore all other cases.
119
00:07:52,920 --> 00:07:54,619
In this module, we've covered the if/else
120
00:07:54,620 --> 00:07:57,990
if/else construct that conditionally runs blocks of code;
121
00:07:59,070 --> 00:08:01,469
the loop keyword that runs a block repeatedly
122
00:08:01,470 --> 00:08:04,769
forever; the while loop that runs code
123
00:08:04,770 --> 00:08:05,950
while a condition is true;
124
00:08:06,980 --> 00:08:17,650
the for loop that iterates over each element in a collection; and the match expression that uses pattern matching and has exhaustiveness checking to handle all possibilities a value might be.
125
00:08:18,940 --> 00:08:20,850
These are the building blocks of complex logic.
126
00:08:22,540 --> 00:08:23,440
Next module,
127
00:08:23,520 --> 00:08:29,050
let's explore enums - a way to define a custom type that works nicely with match expressions.