1
00:00:00,300 --> 00:00:01,710
Welcome to module 3
2
00:00:01,910 --> 00:00:03,630
on handling Result and Option.
3
00:00:05,610 --> 00:00:07,530
In this module, we'll discuss
4
00:00:07,730 --> 00:00:09,389
two types provided by the Standard
5
00:00:09,589 --> 00:00:09,960
Library:
6
00:00:10,440 --> 00:00:11,310
the Result type
7
00:00:11,510 --> 00:00:12,480
and the Option type.
8
00:00:14,590 --> 00:00:16,530
We'll look at what to do when you get
9
00:00:16,730 --> 00:00:18,689
a Result or Option returned
10
00:00:18,889 --> 00:00:20,130
from a function or method call
11
00:00:20,610 --> 00:00:22,739
to either use a successfully produced
12
00:00:22,939 --> 00:00:23,310
value
13
00:00:23,670 --> 00:00:24,350
or a recover
14
00:00:24,550 --> 00:00:25,470
in the failure case.
15
00:00:27,550 --> 00:00:28,250
We'll wrap up
16
00:00:28,450 --> 00:00:30,769
with a discussion of how to turn recoverable
17
00:00:30,969 --> 00:00:33,140
failures into unrecoverable panics
18
00:00:33,340 --> 00:00:33,830
if we want.
19
00:00:35,550 --> 00:00:36,760
Let's start with the Result
20
00:00:36,960 --> 00:00:37,120
type.
21
00:00:38,830 --> 00:00:40,719
Result is an enum defined by the
22
00:00:40,919 --> 00:00:41,710
Standard Library.
23
00:00:42,100 --> 00:00:43,300
It has two variants.
24
00:00:44,570 --> 00:00:46,399
When a function or method returns
25
00:00:46,599 --> 00:00:47,810
a value of type Result,
26
00:00:48,440 --> 00:00:50,540
what it means is that, if everything went well,
27
00:00:50,960 --> 00:00:52,430
you'll get back the Ok variant
28
00:00:52,630 --> 00:00:53,180
of the result
29
00:00:53,390 --> 00:00:54,200
with a value inside.
30
00:00:55,680 --> 00:00:57,690
However, if something went wrong,
31
00:00:57,890 --> 00:00:59,639
you'll get back the Err variant of the
32
00:00:59,839 --> 00:01:00,090
result,
33
00:01:00,540 --> 00:01:02,609
with a value inside that describes more about
34
00:01:02,809 --> 00:01:03,360
what went wrong
35
00:01:03,560 --> 00:01:03,900
and why.
36
00:01:06,120 --> 00:01:08,069
As an example, let's use
37
00:01:08,269 --> 00:01:10,019
the serde_json crate to parse
38
00:01:10,219 --> 00:01:11,920
a string containing some JSON data
39
00:01:12,390 --> 00:01:13,720
into a Rust data type.
40
00:01:15,650 --> 00:01:17,540
Parsing JSON returns a result.
41
00:01:18,380 --> 00:01:19,910
If the JSON is well-formed,
42
00:01:20,300 --> 00:01:21,460
parsing will succeed
43
00:01:21,750 --> 00:01:23,690
and we'll get an instance of a Rust type.
44
00:01:25,380 --> 00:01:27,440
If we have invalid JSON that,
45
00:01:27,640 --> 00:01:29,850
say, has a number as the key
46
00:01:30,210 --> 00:01:31,680
or a trailing comma,
47
00:01:32,190 --> 00:01:33,270
parsing will fail
48
00:01:33,470 --> 00:01:35,189
and we'll get an error that describes the
49
00:01:35,389 --> 00:01:35,750
problem.
50
00:01:37,800 --> 00:01:39,840
Here's some code demonstrating success
51
00:01:40,040 --> 00:01:40,530
and failure.
52
00:01:41,260 --> 00:01:43,320
We're taking some raw strings containing
53
00:01:43,520 --> 00:01:45,449
JSON, which you can imagine might
54
00:01:45,649 --> 00:01:47,279
have come from an API call to a
55
00:01:47,479 --> 00:01:48,120
web service,
56
00:01:48,510 --> 00:01:50,339
and parsing it into instances of a
57
00:01:50,539 --> 00:01:51,030
Person struct.
58
00:01:52,200 --> 00:01:53,360
The first string is a well-formed
59
00:01:53,560 --> 00:01:54,330
JSON
60
00:01:55,340 --> 00:01:57,140
and the second string has a trailing comma.
61
00:01:58,830 --> 00:01:59,930
When we run this code,
62
00:02:00,300 --> 00:02:02,070
we see that the value in first
63
00:02:02,270 --> 00:02:04,410
is the Ok variant containing an instance
64
00:02:04,610 --> 00:02:05,490
of the Person struct.
65
00:02:06,530 --> 00:02:08,480
The value in second is the Err
66
00:02:08,680 --> 00:02:10,519
variant containing an instance
67
00:02:10,719 --> 00:02:12,530
of a serde_json Error struct
68
00:02:12,950 --> 00:02:14,780
that has information on why parsing
69
00:02:14,980 --> 00:02:15,190
failed.
70
00:02:17,000 --> 00:02:18,889
Next, let's look at the Option
71
00:02:19,089 --> 00:02:19,190
type.
72
00:02:20,970 --> 00:02:22,889
Option is similar to Result in
73
00:02:23,089 --> 00:02:24,610
that it also has two variants.
74
00:02:25,590 --> 00:02:27,330
Rather than representing success
75
00:02:27,530 --> 00:02:29,070
and failure that Result does,
76
00:02:29,340 --> 00:02:31,229
the variants of Option represent
77
00:02:31,429 --> 00:02:33,090
the concepts of having something
78
00:02:33,290 --> 00:02:34,170
or having nothing.
79
00:02:35,340 --> 00:02:37,229
If a function returns a value of
80
00:02:37,429 --> 00:02:39,210
type Option, you'll either get
81
00:02:39,410 --> 00:02:40,130
a Some variant
82
00:02:40,330 --> 00:02:41,340
with a value inside,
83
00:02:41,880 --> 00:02:43,770
or you'll get a None variant without
84
00:02:43,970 --> 00:02:45,690
any value because there wasn't anything to
85
00:02:45,890 --> 00:02:46,200
return.
86
00:02:48,230 --> 00:02:50,129
For example, vectors have a
87
00:02:50,329 --> 00:02:52,400
last method that returns an option.
88
00:02:53,270 --> 00:02:55,610
This code will demonstrate how last works.
89
00:02:57,770 --> 00:02:59,840
In the vector named nonempty_list
90
00:03:00,040 --> 00:03:01,450
here, we have a vector
91
00:03:01,650 --> 00:03:03,709
with elements and we're printing out the debug
92
00:03:03,909 --> 00:03:05,230
format of the return value.
93
00:03:07,210 --> 00:03:09,129
We also have an empty_list that we
94
00:03:09,329 --> 00:03:09,930
call last on
95
00:03:10,130 --> 00:03:10,390
and print.
96
00:03:12,620 --> 00:03:14,449
If we run this code, we see
97
00:03:14,649 --> 00:03:16,160
that if the vector has elements,
98
00:03:16,490 --> 00:03:18,619
last returns the Some variant containing
99
00:03:18,819 --> 00:03:20,230
the last element in the vector.
100
00:03:21,650 --> 00:03:23,450
If the vector doesn't have elements,
101
00:03:23,690 --> 00:03:25,820
the last method returns the None variant.
102
00:03:27,520 --> 00:03:29,260
So, once we have a Result
103
00:03:29,460 --> 00:03:31,150
or Option, what do we do with them?
104
00:03:32,420 --> 00:03:34,240
Let's start by looking at the success
105
00:03:34,440 --> 00:03:34,720
case.
106
00:03:36,600 --> 00:03:38,560
If we have a value inside Result's
107
00:03:38,760 --> 00:03:39,420
Ok variant
108
00:03:39,690 --> 00:03:41,519
or Option's Some variant, we
109
00:03:41,719 --> 00:03:43,469
can't use it directly as if it was just
110
00:03:43,669 --> 00:03:45,390
the value - the types don't match.
111
00:03:47,250 --> 00:03:49,379
For example, if we've parsed a JSON
112
00:03:49,579 --> 00:03:51,900
string into a Person instance successfully
113
00:03:52,290 --> 00:03:54,090
and then try to access the name field,
114
00:03:54,570 --> 00:03:56,639
we get an error that says there is no field
115
00:03:56,839 --> 00:03:57,610
`name` on Result.
116
00:03:58,720 --> 00:04:00,639
We need to get the value out of the Ok
117
00:04:00,839 --> 00:04:01,240
variant.
118
00:04:02,790 --> 00:04:03,930
One way we can do that
119
00:04:04,410 --> 00:04:06,060
is by using a match expression
120
00:04:06,260 --> 00:04:07,550
with an arm for the Ok variant
121
00:04:08,520 --> 00:04:10,110
that captures the value inside it,
122
00:04:10,590 --> 00:04:11,460
which we've done here
123
00:04:11,660 --> 00:04:13,080
with a variable named inner.
124
00:04:14,160 --> 00:04:16,010
We then return that value out of
125
00:04:16,210 --> 00:04:16,710
the match
126
00:04:17,860 --> 00:04:19,660
and assign it to the variable first_inner.
127
00:04:21,110 --> 00:04:22,430
And then we can use the person value
128
00:04:22,850 --> 00:04:23,690
we've extracted.
129
00:04:30,200 --> 00:04:32,019
Now, let's talk about what to do in
130
00:04:32,219 --> 00:04:33,010
the failure case.
131
00:04:34,840 --> 00:04:36,789
We can specify the error variant in
132
00:04:36,989 --> 00:04:38,530
another arm of the match expression,
133
00:04:38,950 --> 00:04:39,790
or the None variant
134
00:04:39,990 --> 00:04:40,870
if we have an Option,
135
00:04:41,560 --> 00:04:43,569
and the code we put in that arm depends
136
00:04:43,769 --> 00:04:44,680
on what we want to do
137
00:04:44,920 --> 00:04:45,760
in case of a problem.
138
00:04:47,260 --> 00:04:49,180
For example, trying to parse
139
00:04:49,380 --> 00:04:50,079
a JSON string
140
00:04:50,279 --> 00:04:51,939
with a trailing comma will put us in
141
00:04:52,139 --> 00:04:53,769
the Err case where we could choose
142
00:04:53,969 --> 00:04:55,300
to return a default value.
143
00:04:56,800 --> 00:04:58,689
We could also choose to handle different
144
00:04:58,889 --> 00:04:59,830
errors differently.
145
00:05:00,370 --> 00:05:02,440
We do that by capturing the inner
146
00:05:02,640 --> 00:05:04,690
Err information by using a variable
147
00:05:04,960 --> 00:05:06,160
instead of an underscore.
148
00:05:06,640 --> 00:05:08,649
And then in the code block, we can take
149
00:05:08,849 --> 00:05:10,600
different actions based on the properties
150
00:05:10,800 --> 00:05:11,430
of the error.
151
00:05:13,220 --> 00:05:15,020
We saw earlier that this call
152
00:05:15,220 --> 00:05:16,970
to from_serde
153
00:05:17,240 --> 00:05:18,010
returns a serde_json error.
154
00:05:20,010 --> 00:05:21,839
This Error struct has a number of
155
00:05:22,039 --> 00:05:24,060
methods on it to get more information
156
00:05:24,260 --> 00:05:25,919
about the error so we can decide what
157
00:05:26,119 --> 00:05:26,640
to do about it.
158
00:05:28,940 --> 00:05:30,770
For example, this is_eof
159
00:05:31,450 --> 00:05:33,409
method is useful if we're attempting
160
00:05:33,609 --> 00:05:34,760
to process streaming data.
161
00:05:35,390 --> 00:05:37,279
If that's the case, we could try
162
00:05:37,479 --> 00:05:38,960
to recover by reading more data
163
00:05:39,160 --> 00:05:39,830
and retrying.
164
00:05:41,980 --> 00:05:43,820
Finally, let's talk about a choice
165
00:05:44,020 --> 00:05:45,699
you always have - turning a
166
00:05:45,899 --> 00:05:48,159
recoverable error into an unrecoverable
167
00:05:48,359 --> 00:05:48,520
one.
168
00:05:50,020 --> 00:05:51,969
In the match expression arm, where we're
169
00:05:52,169 --> 00:05:53,550
handling an Err variant,
170
00:05:54,100 --> 00:05:55,960
we can choose to call the panic! macro to
171
00:05:56,160 --> 00:05:57,879
end execution for all the
172
00:05:58,079 --> 00:06:00,060
reasons we learned about in the previous module.
173
00:06:01,820 --> 00:06:03,740
It's not possible to turn an
174
00:06:03,940 --> 00:06:05,679
unrecoverable error into a
175
00:06:05,879 --> 00:06:07,820
recoverable one. Therefore,
176
00:06:08,020 --> 00:06:10,450
Result gives callers the most flexibility.
177
00:06:12,510 --> 00:06:14,370
If the match expressions we used in this
178
00:06:14,570 --> 00:06:14,940
module
179
00:06:15,300 --> 00:06:16,890
look messy and verbose to you,
180
00:06:17,250 --> 00:06:19,349
keep watching! In a few modules
181
00:06:19,549 --> 00:06:21,299
from now, we'll be looking at some ways
182
00:06:21,499 --> 00:06:22,170
to improve this code.
183
00:06:24,250 --> 00:06:26,099
The improvements are variations on
184
00:06:26,299 --> 00:06:28,110
the behavior of this match expression, though,
185
00:06:28,440 --> 00:06:30,210
so it's important to understand this basic
186
00:06:30,410 --> 00:06:30,750
case.
187
00:06:33,020 --> 00:06:33,960
In this module,
188
00:06:34,220 --> 00:06:35,890
we discussed the Result enum
189
00:06:36,100 --> 00:06:38,300
that has the variants Ok and Err
190
00:06:38,720 --> 00:06:39,859
to represent success
191
00:06:40,059 --> 00:06:40,510
and failure,
192
00:06:40,940 --> 00:06:43,160
and the Option enum that has the variants
193
00:06:43,360 --> 00:06:45,139
Some and None to represent
194
00:06:45,339 --> 00:06:46,260
something or nothing.
195
00:06:47,910 --> 00:06:49,829
We looked at examples using a match
196
00:06:50,029 --> 00:06:51,780
expression to extract the value
197
00:06:51,980 --> 00:06:52,950
in the success case
198
00:06:53,150 --> 00:06:55,230
and attempt to recover in the failure case
199
00:06:55,430 --> 00:06:57,419
by taking an action like using a default
200
00:06:57,619 --> 00:06:58,890
value or retrying.
201
00:07:00,360 --> 00:07:02,490
We also talked about using the panic! macro
202
00:07:02,690 --> 00:07:05,010
within the match to turn a recoverable
203
00:07:05,210 --> 00:07:06,950
error into an unrecoverable one
204
00:07:07,150 --> 00:07:07,560
if we want.
205
00:07:09,690 --> 00:07:11,789
Next, let's look at returning Result
206
00:07:11,989 --> 00:07:13,829
from functions and using the ?
207
00:07:14,029 --> 00:07:14,640
operator.