1 00:00:06,666 --> 00:00:08,010 - In the previous session, 2 00:00:08,010 --> 00:00:10,710 I showed the Option enum type. 3 00:00:10,710 --> 00:00:13,440 Typically used in a function that may return a value 4 00:00:13,440 --> 00:00:15,240 or may return no value. 5 00:00:15,240 --> 00:00:17,730 There's a similar enum type called Result, 6 00:00:17,730 --> 00:00:22,500 where it represents either a value or an error. 7 00:00:22,500 --> 00:00:24,180 So the result type is actually 8 00:00:24,180 --> 00:00:29,180 has two generic type parameters and two variants. 9 00:00:29,430 --> 00:00:31,410 When you create a result object, 10 00:00:31,410 --> 00:00:33,663 it'll either have the Ok variant, 11 00:00:34,573 --> 00:00:37,770 in which case it represents a successful outcome 12 00:00:37,770 --> 00:00:40,350 and it'll have a value of some type T, 13 00:00:40,350 --> 00:00:41,970 which might be an integer or string, 14 00:00:41,970 --> 00:00:44,880 or whatever type you are trying to return. 15 00:00:44,880 --> 00:00:47,760 Or, if you want to indicate an error, 16 00:00:47,760 --> 00:00:49,650 then you'd set it to this variant, 17 00:00:49,650 --> 00:00:53,040 and then basically it contains some kind of error object, 18 00:00:53,040 --> 00:00:56,310 like an exception in other languages, okay? 19 00:00:56,310 --> 00:01:00,630 So, Result is useful in functions which might fail. 20 00:01:00,630 --> 00:01:02,730 So if you try to connect with database, 21 00:01:02,730 --> 00:01:04,350 it could give you back a connection, 22 00:01:04,350 --> 00:01:06,840 or it could give you back an error indicating 23 00:01:06,840 --> 00:01:08,193 that it's not possible. 24 00:01:09,270 --> 00:01:11,820 So the Result enum type represents 25 00:01:11,820 --> 00:01:14,460 either a successful value. 26 00:01:14,460 --> 00:01:17,430 If the variant is Ok, 27 00:01:17,430 --> 00:01:19,620 you'll get back a value of some type. 28 00:01:19,620 --> 00:01:23,850 Or, if the variant is error or Err, 29 00:01:23,850 --> 00:01:25,650 then it represents an error type. 30 00:01:25,650 --> 00:01:27,840 Basically some kind of error object 31 00:01:27,840 --> 00:01:29,853 which will describe what went wrong. 32 00:01:31,470 --> 00:01:35,460 So, this is actually how Rust deals with errors. 33 00:01:35,460 --> 00:01:37,350 Most languages you might have come across 34 00:01:37,350 --> 00:01:42,000 like Java, and C#, and C++, Python have exception handling. 35 00:01:42,000 --> 00:01:44,340 We have it at a try-catch block. 36 00:01:44,340 --> 00:01:45,570 Rust doesn't have that. 37 00:01:45,570 --> 00:01:47,640 It doesn't have a try block or a catch block, 38 00:01:47,640 --> 00:01:51,030 or finally, when a function could fail, 39 00:01:51,030 --> 00:01:52,710 it doesn't throw an exception. 40 00:01:52,710 --> 00:01:54,810 It returns a Result enum, 41 00:01:54,810 --> 00:01:56,943 and the Result enum will be set to be Err, 42 00:01:57,900 --> 00:02:00,900 and it'll kind of indicate what return type it is. 43 00:02:00,900 --> 00:02:02,850 So, the flow of control 44 00:02:02,850 --> 00:02:05,130 in the Rust application is actually simpler. 45 00:02:05,130 --> 00:02:07,170 When you call a function that fails, 46 00:02:07,170 --> 00:02:08,400 it'll return a result. 47 00:02:08,400 --> 00:02:11,220 You can check the result to see whether it's okay 48 00:02:11,220 --> 00:02:12,420 or whether it's an error. 49 00:02:12,420 --> 00:02:15,960 Much more kind of deterministic, much easier to see the flow 50 00:02:15,960 --> 00:02:17,223 in the Rust application. 51 00:02:18,270 --> 00:02:19,650 So like I said, 52 00:02:19,650 --> 00:02:23,250 the Result enum type is typically used for a function 53 00:02:23,250 --> 00:02:26,280 that may succeed with the Ok status, 54 00:02:26,280 --> 00:02:29,250 or it might fail with the Err status 55 00:02:29,250 --> 00:02:32,940 depending on the variant that's set inside the result. 56 00:02:32,940 --> 00:02:35,910 It'll tell you whether it worked or whether it failed. 57 00:02:35,910 --> 00:02:38,160 A good example from the standard library, 58 00:02:38,160 --> 00:02:41,100 this is used a lot in the standard library, the result type, 59 00:02:41,100 --> 00:02:44,970 there's a function called from_str_radix. 60 00:02:44,970 --> 00:02:47,940 You give it a string, and later on in the course, 61 00:02:47,940 --> 00:02:51,000 I'm gonna have to explain the difference between str, 62 00:02:51,000 --> 00:02:52,113 that you see here, 63 00:02:53,580 --> 00:02:56,640 and string, that we've seen as well. 64 00:02:56,640 --> 00:03:01,140 Technically, string is the primary data type 65 00:03:01,140 --> 00:03:02,740 to represent text 66 00:03:04,380 --> 00:03:05,610 as a structure, 67 00:03:05,610 --> 00:03:09,690 and str is a slice part of an existing string, 68 00:03:09,690 --> 00:03:11,208 like a viewport. 69 00:03:11,208 --> 00:03:13,380 A str is like a viewport 70 00:03:13,380 --> 00:03:16,410 or slice into an existing string object. 71 00:03:16,410 --> 00:03:19,110 So that's a little bit complicated. 72 00:03:19,110 --> 00:03:21,930 So we'll discuss that later. 73 00:03:21,930 --> 00:03:25,800 So for now we'll just kind of blur the eyes a little bit, 74 00:03:25,800 --> 00:03:28,080 and I'll say, when you call this function, 75 00:03:28,080 --> 00:03:30,123 you can pass in some text. 76 00:03:31,110 --> 00:03:32,850 Basically a string representing numbers 77 00:03:32,850 --> 00:03:35,340 like 1, 2, 3, 4, 5 as a string, 78 00:03:35,340 --> 00:03:37,590 and a radix, or radix, is the base, 79 00:03:37,590 --> 00:03:42,330 like Base 10, or Base 16 for hex, or Base 8 for octo. 80 00:03:42,330 --> 00:03:44,430 And what the function attempts to do 81 00:03:44,430 --> 00:03:46,920 is to parse this string, 82 00:03:46,920 --> 00:03:48,450 and give you back a number. 83 00:03:48,450 --> 00:03:49,980 You pass in a string. 84 00:03:49,980 --> 00:03:53,787 You pass in something like "123," 85 00:03:54,870 --> 00:03:59,100 like that, and you pass in radix, or radix, like 10. 86 00:03:59,100 --> 00:04:02,520 And hopefully what it'll do is give you back an Ok result 87 00:04:02,520 --> 00:04:04,803 of type i32, like this. 88 00:04:06,330 --> 00:04:09,120 Okay, but, of course, it could fail. 89 00:04:09,120 --> 00:04:11,160 When you pass in strings, 90 00:04:11,160 --> 00:04:14,670 imagine the user pass in something that wasn't possible, 91 00:04:14,670 --> 00:04:15,843 like "wibble." 92 00:04:17,190 --> 00:04:18,123 My favorite word. 93 00:04:19,560 --> 00:04:23,250 Okay, if you pass in an invalid numeric string, 94 00:04:23,250 --> 00:04:24,270 it's gonna fail. 95 00:04:24,270 --> 00:04:25,170 In that case, 96 00:04:25,170 --> 00:04:28,920 the result that comes back will be this variant. 97 00:04:28,920 --> 00:04:31,620 You'll either get back an Ok result, 98 00:04:31,620 --> 00:04:33,660 or you'll get back an Err result 99 00:04:33,660 --> 00:04:35,133 to tell you that it failed. 100 00:04:36,870 --> 00:04:37,770 So, there we go. 101 00:04:37,770 --> 00:04:40,050 When you call the function, it'll return a result. 102 00:04:40,050 --> 00:04:42,720 The variant will either be the Ok variant, 103 00:04:42,720 --> 00:04:45,090 in which case you can get the number that came back, 104 00:04:45,090 --> 00:04:48,840 like "123," or it'll be the Err variant, 105 00:04:48,840 --> 00:04:51,510 in which case you can get back the error object, 106 00:04:51,510 --> 00:04:53,190 which is effectively like an exception 107 00:04:53,190 --> 00:04:54,363 in other languages. 108 00:04:55,440 --> 00:04:58,110 Right, so this is how it would look. 109 00:04:58,110 --> 00:04:59,820 Have a look at this example here. 110 00:04:59,820 --> 00:05:02,130 I've declared a variable res. 111 00:05:02,130 --> 00:05:05,463 It's a result that may contain an integer 32, 112 00:05:06,360 --> 00:05:08,463 or it might contain a ParseIntError. 113 00:05:09,720 --> 00:05:12,690 From a technical language point of view, 114 00:05:12,690 --> 00:05:16,170 std is the standard crate in Rust, 115 00:05:16,170 --> 00:05:21,060 num is a module, and ParseIntError is a structure, 116 00:05:21,060 --> 00:05:23,700 a bit like a class, defined in that module. 117 00:05:23,700 --> 00:05:28,700 A Java developer might say it's like a class in a package. 118 00:05:28,980 --> 00:05:33,780 A C++ developer might say it's like a class in a namespace. 119 00:05:33,780 --> 00:05:38,100 And a Rust developer would say it's a structure in a module 120 00:05:38,100 --> 00:05:40,650 in the standard library, the standard crate. 121 00:05:40,650 --> 00:05:43,380 Anyway, that's the type of error that might come back, 122 00:05:43,380 --> 00:05:44,370 and that's the type of number 123 00:05:44,370 --> 00:05:46,170 that might come back if it was okay. 124 00:05:48,570 --> 00:05:50,790 Upon the i32 type, 125 00:05:50,790 --> 00:05:55,320 from_str_radix is defined in the i32 type. 126 00:05:55,320 --> 00:06:00,320 Technically, this is a static method in the i32 structure. 127 00:06:00,720 --> 00:06:02,270 Anyway, we call from_str_radix. 128 00:06:03,810 --> 00:06:06,040 It's a bit like saying Int.parseInt 129 00:06:07,050 --> 00:06:08,250 in other languages. 130 00:06:08,250 --> 00:06:09,540 We give it some string, 131 00:06:09,540 --> 00:06:12,900 like some kind of hopefully numeric string. 132 00:06:12,900 --> 00:06:16,020 I mean, that's the idea of it, something like that. 133 00:06:16,020 --> 00:06:17,430 It's what we passed in. 134 00:06:17,430 --> 00:06:20,040 And we're gonna get back a result object, 135 00:06:20,040 --> 00:06:23,853 which may be the Ok variant, 136 00:06:24,690 --> 00:06:28,170 in which case effectively the result that we get back. 137 00:06:28,170 --> 00:06:30,300 I just tidy up my picture. 138 00:06:30,300 --> 00:06:32,700 If the result is Ok, 139 00:06:32,700 --> 00:06:35,493 then what we'll be getting back is the i32. 140 00:06:36,690 --> 00:06:39,360 But the result could be an error obviously, 141 00:06:39,360 --> 00:06:42,480 in which case the error we get back will be that type. 142 00:06:42,480 --> 00:06:45,810 Right, so which we can then display the number like "123," 143 00:06:45,810 --> 00:06:49,710 or we can display the error like ParseIntError 144 00:06:49,710 --> 00:06:51,000 on the console. 145 00:06:51,000 --> 00:06:54,180 Okay, so this is how you do the equivalent 146 00:06:54,180 --> 00:06:56,400 of exception handling in other languages, 147 00:06:56,400 --> 00:06:58,650 in Java, in C++, in C#. 148 00:06:58,650 --> 00:07:00,360 You'd have to try-catch block, 149 00:07:00,360 --> 00:07:02,880 and you'd catch a ParseIntError. 150 00:07:02,880 --> 00:07:05,040 In Rust, you just call the function, 151 00:07:05,040 --> 00:07:06,510 and it returns the value. 152 00:07:06,510 --> 00:07:08,160 That value might be an error, 153 00:07:08,160 --> 00:07:10,053 and then you can check it, like this. 154 00:07:11,700 --> 00:07:15,780 There is a bunch of methods defined in the Result enum, 155 00:07:15,780 --> 00:07:16,743 like unwrap_or. 156 00:07:17,850 --> 00:07:19,410 We've seen something similar to this. 157 00:07:19,410 --> 00:07:22,020 Very similar, in fact, with the Option enum type. 158 00:07:22,020 --> 00:07:23,790 When you have a Result enum, 159 00:07:23,790 --> 00:07:26,140 you can attempt, you can call the unwrap_or 160 00:07:27,300 --> 00:07:29,880 if the result contains an actual value. 161 00:07:29,880 --> 00:07:31,830 It'll give you back the value. 162 00:07:31,830 --> 00:07:35,430 Otherwise, it'll give you back the default value 163 00:07:35,430 --> 00:07:36,263 that you supply. 164 00:07:36,263 --> 00:07:37,380 When you call this function, 165 00:07:37,380 --> 00:07:39,930 you pass in a default value, 166 00:07:39,930 --> 00:07:41,880 and that's the value you'll get back 167 00:07:41,880 --> 00:07:43,353 if it was an error. 168 00:07:45,000 --> 00:07:45,870 Right. 169 00:07:45,870 --> 00:07:47,820 So, it would look like this. 170 00:07:47,820 --> 00:07:50,250 Here's some kind of result object. 171 00:07:50,250 --> 00:07:53,490 It may contain hopefully an Ok integer, 172 00:07:53,490 --> 00:07:55,800 or it could contain an error. 173 00:07:55,800 --> 00:07:58,020 Attempt to unwrap it, 174 00:07:58,020 --> 00:08:01,260 and give me back the value as an i32. 175 00:08:01,260 --> 00:08:04,830 If it failed, then this will be the replacement. 176 00:08:04,830 --> 00:08:08,130 Instead of getting an actual i32 out of the value, 177 00:08:08,130 --> 00:08:10,680 we'll get this value out of it instead 178 00:08:10,680 --> 00:08:13,500 because it was actually in an error state, okay? 179 00:08:13,500 --> 00:08:15,660 So basically suppress the error 180 00:08:15,660 --> 00:08:18,603 and give me back that value instead. 181 00:08:20,070 --> 00:08:24,120 Right, so unwrap_or is one function available, 182 00:08:24,120 --> 00:08:27,000 but there are many other functions or methods also available 183 00:08:27,000 --> 00:08:29,070 in the Result enum type. 184 00:08:29,070 --> 00:08:30,660 So if you look at the documentation, 185 00:08:30,660 --> 00:08:33,390 go into the documentation for Rust online 186 00:08:33,390 --> 00:08:35,550 in the standard crate, 187 00:08:35,550 --> 00:08:37,770 in the result module. 188 00:08:37,770 --> 00:08:40,830 That's where the Result enum is defined. 189 00:08:40,830 --> 00:08:43,140 So let's take a look at that. 190 00:08:43,140 --> 00:08:44,010 Here we are. 191 00:08:44,010 --> 00:08:48,390 This is the documentation in the Rust online documentation 192 00:08:48,390 --> 00:08:50,610 for the standard crate, 193 00:08:50,610 --> 00:08:54,060 for the result module, which is like a namespace, remember? 194 00:08:54,060 --> 00:08:57,750 Here we are, in the std result module, 195 00:08:57,750 --> 00:08:59,310 and you can kind of scroll through 196 00:08:59,310 --> 00:09:02,460 some narrative explanation of what's going on here. 197 00:09:02,460 --> 00:09:05,670 Some syntax we haven't covered yet obviously, but we will. 198 00:09:05,670 --> 00:09:08,643 Let's click on the Enums link here. 199 00:09:09,810 --> 00:09:11,010 And at the bottom, 200 00:09:11,010 --> 00:09:13,050 you'll see there's an enum type called Result. 201 00:09:13,050 --> 00:09:14,190 Yes, that's what we're looking for. 202 00:09:14,190 --> 00:09:15,093 Let's click there. 203 00:09:16,140 --> 00:09:18,810 So this is the Result enum type 204 00:09:18,810 --> 00:09:21,990 defined in the result module in the standard crate. 205 00:09:21,990 --> 00:09:24,810 It's an enum as described. 206 00:09:24,810 --> 00:09:26,790 It has the Ok variant, 207 00:09:26,790 --> 00:09:29,640 in which case it has some value like a i32, 208 00:09:29,640 --> 00:09:31,280 or the Err variant, 209 00:09:31,280 --> 00:09:34,080 in which case you're gonna get some kind of error object. 210 00:09:34,080 --> 00:09:36,540 And these are the various methods you can call 211 00:09:36,540 --> 00:09:39,060 upon a Result enum. 212 00:09:39,060 --> 00:09:42,033 Okay, so the one we just looked at was unwrap_or. 213 00:09:44,596 --> 00:09:47,100 Okay, so it kind of explains the usage. 214 00:09:47,100 --> 00:09:48,120 The other functions here, 215 00:09:48,120 --> 00:09:50,130 obviously you can have a look at as well. 216 00:09:50,130 --> 00:09:52,950 So do spend a while looking through these functions 217 00:09:52,950 --> 00:09:54,750 when you get a moment. 218 00:09:54,750 --> 00:09:56,670 Right, let's take a look at an example then 219 00:09:56,670 --> 00:09:59,430 in the lesson04_enums project. 220 00:09:59,430 --> 00:10:02,550 We're gonna look at the demo_using_result_enum, 221 00:10:02,550 --> 00:10:05,520 and then we'll run the application and see how it looks. 222 00:10:05,520 --> 00:10:08,580 Right, here's my lesson04_enums project. 223 00:10:08,580 --> 00:10:11,100 This is the last time we're gonna look at this 224 00:10:11,100 --> 00:10:12,360 in this lesson. 225 00:10:12,360 --> 00:10:15,000 In main.rs, 226 00:10:15,000 --> 00:10:17,340 let's uncomment the code 227 00:10:17,340 --> 00:10:19,503 for that function demo_using_result_enum. 228 00:10:21,720 --> 00:10:22,653 Very good. 229 00:10:24,210 --> 00:10:26,466 It is here. 230 00:10:26,466 --> 00:10:27,299 Let's have a look. 231 00:10:27,299 --> 00:10:28,259 Oh, it's here. 232 00:10:28,259 --> 00:10:29,092 Here it is. 233 00:10:30,600 --> 00:10:35,600 So, I declare a res variable of type Result. 234 00:10:36,270 --> 00:10:41,010 It could contain an Ok i32, or it could be an Err, 235 00:10:41,010 --> 00:10:43,380 in which case the error that you'll get back 236 00:10:43,380 --> 00:10:45,630 when you call the parse function 237 00:10:45,630 --> 00:10:49,020 and from_str_radix function. 238 00:10:49,020 --> 00:10:51,900 The error type that it returns is that error type. 239 00:10:51,900 --> 00:10:55,110 That's the error object you could get back. 240 00:10:55,110 --> 00:10:56,520 So, let's see. 241 00:10:56,520 --> 00:10:58,020 First of all, I call the function. 242 00:10:58,020 --> 00:11:02,580 I pass in a valid hexadecimal string. 243 00:11:02,580 --> 00:11:04,470 FF is 244 00:11:04,470 --> 00:11:08,790 255, I think, as an actual number. 245 00:11:08,790 --> 00:11:12,090 So this res will have the Ok variant, 246 00:11:12,090 --> 00:11:14,760 which should get extracted into n. 247 00:11:14,760 --> 00:11:17,010 And I'm thinking it should be 255. 248 00:11:17,010 --> 00:11:18,753 Let's give that a spin. 249 00:11:20,310 --> 00:11:24,780 My hexadecimal mental calculations are not legendary. 250 00:11:24,780 --> 00:11:26,280 Let's hope I got that right. 251 00:11:26,280 --> 00:11:27,450 Cargo run. 252 00:11:27,450 --> 00:11:30,690 We've got those warnings about functions at the top. 253 00:11:30,690 --> 00:11:32,790 So I think if I give it FF, 254 00:11:32,790 --> 00:11:35,910 that is a valid hexadecimal string. 255 00:11:35,910 --> 00:11:37,980 So all good here. 256 00:11:37,980 --> 00:11:39,540 It parsed the string. 257 00:11:39,540 --> 00:11:44,497 Basically it returned an Ok, and the Ok value was an i32. 258 00:11:45,780 --> 00:11:47,640 That's the value that we'll extract. 259 00:11:47,640 --> 00:11:49,020 Pattern matched. 260 00:11:49,020 --> 00:11:52,830 Extract the value from the Ok variant if you like, 261 00:11:52,830 --> 00:11:53,940 and output it. 262 00:11:53,940 --> 00:11:56,310 And it's 255. 263 00:11:56,310 --> 00:11:58,020 And then at the end, 264 00:11:58,020 --> 00:11:59,760 here I've got res2. 265 00:12:00,660 --> 00:12:04,350 I've parsed res2 as an integer, like that. 266 00:12:04,350 --> 00:12:05,970 And that's gonna work, okay? 267 00:12:05,970 --> 00:12:10,200 So that will also be unwrap successfully as 255. 268 00:12:10,200 --> 00:12:11,760 So that's good. 269 00:12:11,760 --> 00:12:12,840 And then what I'll do here is, 270 00:12:12,840 --> 00:12:14,640 I'll kind of comment that one out, 271 00:12:14,640 --> 00:12:16,860 and I'll uncomment that line. 272 00:12:16,860 --> 00:12:19,530 This is clearly an invalid string. 273 00:12:19,530 --> 00:12:21,060 So that's gonna fail, 274 00:12:21,060 --> 00:12:24,240 but it'll return a result 275 00:12:24,240 --> 00:12:26,610 with the Err variant. 276 00:12:26,610 --> 00:12:27,630 And I'll come in here, 277 00:12:27,630 --> 00:12:31,080 and I'll basically extract the Err variant, 278 00:12:31,080 --> 00:12:34,113 and it'll print the error message there. 279 00:12:36,150 --> 00:12:38,010 And similarly here, 280 00:12:38,010 --> 00:12:40,980 if I give it an invalid string here like "wobble," 281 00:12:40,980 --> 00:12:42,450 wibble wobble, 282 00:12:42,450 --> 00:12:43,503 jelly on a plate, 283 00:12:44,400 --> 00:12:48,600 when it attempts to extract, that's gonna return result. 284 00:12:48,600 --> 00:12:49,680 It will try to unwrap it. 285 00:12:49,680 --> 00:12:51,870 It fails basically because there's an error, 286 00:12:51,870 --> 00:12:54,540 and it'll give me back a value -1 instead. 287 00:12:54,540 --> 00:12:56,100 It kinda swallows the error, 288 00:12:56,100 --> 00:12:58,590 and give me back a default value instead. 289 00:12:58,590 --> 00:13:00,750 Right, so this is gonna be the last demo 290 00:13:00,750 --> 00:13:03,240 we're going to run hopefully in this lesson. 291 00:13:03,240 --> 00:13:04,473 Let's hope it works. 292 00:13:07,620 --> 00:13:08,453 Fantastic. 293 00:13:08,453 --> 00:13:11,820 So when I gave it an invalid string, 294 00:13:11,820 --> 00:13:15,060 it returned in a result that was an error state, 295 00:13:15,060 --> 00:13:16,860 and it matched this pattern, 296 00:13:16,860 --> 00:13:18,120 and it says an error occurred, 297 00:13:18,120 --> 00:13:20,400 and then it printed the error object. 298 00:13:20,400 --> 00:13:23,760 So the error occurred, and this is the error object. 299 00:13:23,760 --> 00:13:25,800 Error objects have some kind of string, 300 00:13:25,800 --> 00:13:28,080 like a message to say how it went wrong. 301 00:13:28,080 --> 00:13:31,140 So when you print an error message, an error object, 302 00:13:31,140 --> 00:13:33,630 it'll give you back something meaningful. 303 00:13:33,630 --> 00:13:36,780 If you try to unwrap a result that's in error, 304 00:13:36,780 --> 00:13:38,400 it'll just give you back the default value 305 00:13:38,400 --> 00:13:40,290 that you told it to. 306 00:13:40,290 --> 00:13:42,000 It fails gracefully, 307 00:13:42,000 --> 00:13:45,270 because maybe -1 would be good enough in our scenario. 308 00:13:45,270 --> 00:13:49,080 So the unwrapped result now would be -1. 309 00:13:49,080 --> 00:13:51,690 Okay, so that concludes the lesson. 310 00:13:51,690 --> 00:13:52,890 We've looked at enums. 311 00:13:52,890 --> 00:13:55,350 We've seen how enums can convey data. 312 00:13:55,350 --> 00:13:56,970 We looked at the Option enum 313 00:13:56,970 --> 00:13:59,370 that can contain a value or none. 314 00:13:59,370 --> 00:14:02,070 And then finally, we've looked at the Result enum 315 00:14:02,070 --> 00:14:04,697 that can contain a value or an error message, okay? 316 00:14:04,697 --> 00:14:06,450 And in the rest of the course, 317 00:14:06,450 --> 00:14:09,570 we're going to be using enums as appropriate 318 00:14:09,570 --> 00:14:12,030 to indicate errors, optional values, 319 00:14:12,030 --> 00:14:14,613 and other state machines of our choosing.