1 00:00:06,709 --> 00:00:07,980 - In the previous section, 2 00:00:07,980 --> 00:00:11,400 we saw how to define enums that can convey values 3 00:00:11,400 --> 00:00:12,840 in their variance. 4 00:00:12,840 --> 00:00:15,870 It's a very useful mechanism and it's used a lot 5 00:00:15,870 --> 00:00:18,690 in some of the standard enums in the rust library. 6 00:00:18,690 --> 00:00:21,870 And here's a good example, the option enum type. 7 00:00:21,870 --> 00:00:26,100 Basically it represents a value that may be there 8 00:00:26,100 --> 00:00:27,660 or may not be there. 9 00:00:27,660 --> 00:00:30,360 It's kind of the equivalent of an optional variable 10 00:00:30,360 --> 00:00:35,360 in Java or an nullable variable in .net, okay? 11 00:00:35,490 --> 00:00:38,370 It may have a value or it may have no value at all. 12 00:00:38,370 --> 00:00:40,200 It's like an optional value. 13 00:00:40,200 --> 00:00:44,280 So in terms of the syntax, option is a generic type. 14 00:00:44,280 --> 00:00:45,390 When you create an option, 15 00:00:45,390 --> 00:00:47,370 you've gotta tell it what type T represents, 16 00:00:47,370 --> 00:00:49,290 like an integer for example, 17 00:00:49,290 --> 00:00:51,450 and then when you create an option value 18 00:00:51,450 --> 00:00:54,060 it can either be in the state sum, 19 00:00:54,060 --> 00:00:56,400 in which case it contains a value of that type, 20 00:00:56,400 --> 00:00:59,700 like an integer, or it can be in state none, 21 00:00:59,700 --> 00:01:01,140 which means it doesn't represent, 22 00:01:01,140 --> 00:01:02,763 it doesn't have a value at all. 23 00:01:03,870 --> 00:01:06,510 So it represents an optional value. 24 00:01:06,510 --> 00:01:09,420 It might contain a value of some type T 25 00:01:09,420 --> 00:01:10,740 if it's in this state 26 00:01:10,740 --> 00:01:14,523 or if it's in this state, it has no value at all. 27 00:01:15,960 --> 00:01:18,240 The main reason or one of the main reasons 28 00:01:18,240 --> 00:01:22,080 for using option is to represent a nullable type 29 00:01:22,080 --> 00:01:23,940 that could be returned from a function. 30 00:01:23,940 --> 00:01:25,800 For example, you call the function 31 00:01:25,800 --> 00:01:30,510 and in other languages if you wanted to indicate, you know, 32 00:01:30,510 --> 00:01:33,660 that the function failed, you might return null. 33 00:01:33,660 --> 00:01:36,120 But working with null is quite dangerous. 34 00:01:36,120 --> 00:01:38,310 You can get into, kind of, null point of exceptions 35 00:01:38,310 --> 00:01:39,900 and the program crashes. 36 00:01:39,900 --> 00:01:43,140 So rust doesn't really have the concept of null. 37 00:01:43,140 --> 00:01:45,270 It has an option, instead. 38 00:01:45,270 --> 00:01:46,770 Whenever you want to say, 39 00:01:46,770 --> 00:01:50,640 this function may return a value or it might not 40 00:01:50,640 --> 00:01:52,770 then you return an option, okay? 41 00:01:52,770 --> 00:01:54,660 And then the caller, 42 00:01:54,660 --> 00:01:56,820 when they get the option value back, 43 00:01:56,820 --> 00:01:59,760 they can check, does it contain some value 44 00:01:59,760 --> 00:02:02,220 or does it contain no value at all? 45 00:02:02,220 --> 00:02:05,520 Safer than dealing directly with null pointers. 46 00:02:05,520 --> 00:02:07,980 It avoids potential null point of exceptions 47 00:02:07,980 --> 00:02:10,350 that you might get in other languages. 48 00:02:10,350 --> 00:02:12,060 So here is an example. 49 00:02:12,060 --> 00:02:15,669 I've got a function called second of day, 50 00:02:15,669 --> 00:02:17,730 and you pass in the hour, the minute, 51 00:02:17,730 --> 00:02:20,340 and the second of a current time 52 00:02:20,340 --> 00:02:23,430 and the function, this is how you designate the return type 53 00:02:23,430 --> 00:02:26,070 of a function at the end of the function signature, 54 00:02:26,070 --> 00:02:30,120 the function takes in an hour as an unsigned 32 bit integer, 55 00:02:30,120 --> 00:02:32,790 the current minute and the current second 56 00:02:32,790 --> 00:02:35,880 and it returns an option, okay? 57 00:02:35,880 --> 00:02:38,580 So it's gonna return you the current second of the day 58 00:02:38,580 --> 00:02:43,580 from midnight, but maybe it doesn't return the value at all. 59 00:02:43,680 --> 00:02:48,090 So hopefully it'll return some value of type u32 60 00:02:48,090 --> 00:02:50,280 or maybe it'll return none. 61 00:02:50,280 --> 00:02:53,520 So what it does, it basically does an error check in. 62 00:02:53,520 --> 00:02:58,520 It says, if the hour is less than 23, oh, first of all, 63 00:02:58,740 --> 00:03:00,840 because the hour is unsigned, 64 00:03:00,840 --> 00:03:02,480 then it can't be negative, okay? 65 00:03:02,480 --> 00:03:04,980 So it could only be zero or above, 66 00:03:04,980 --> 00:03:07,320 if it's less than or equal to 23, 67 00:03:07,320 --> 00:03:10,560 and if the minute is less than or equal to 59, 68 00:03:10,560 --> 00:03:13,500 and if the second is also less than or equal to 59, 69 00:03:13,500 --> 00:03:14,760 then that's valid. 70 00:03:14,760 --> 00:03:16,650 In which case we return 71 00:03:16,650 --> 00:03:20,850 or we calculate how many seconds there are past midnight. 72 00:03:20,850 --> 00:03:23,613 There were 3,600 seconds per hour. 73 00:03:24,450 --> 00:03:26,580 There were 60 seconds per minute, 74 00:03:26,580 --> 00:03:29,340 plus whatever the seconds are into the current minute 75 00:03:29,340 --> 00:03:32,130 that will give you the number of seconds 76 00:03:32,130 --> 00:03:34,410 that you are into the day. 77 00:03:34,410 --> 00:03:36,330 A bit contrived, but there we go. 78 00:03:36,330 --> 00:03:39,480 And it returns Option::Some. 79 00:03:39,480 --> 00:03:42,900 This is how you create an option variable. 80 00:03:42,900 --> 00:03:45,390 You give it the variant type - some 81 00:03:45,390 --> 00:03:49,680 and because it was defined to be a u32 82 00:03:49,680 --> 00:03:51,720 we give it a u32 value. 83 00:03:51,720 --> 00:03:56,490 Secs, seconds here is an unsigned 32 bit integer. 84 00:03:56,490 --> 00:04:01,490 So the function will hopefully return some u32 value 85 00:04:01,980 --> 00:04:04,440 or it'll return none. 86 00:04:04,440 --> 00:04:06,020 It'll either be in that state 87 00:04:06,020 --> 00:04:09,780 in which case it contains a value of interest 88 00:04:09,780 --> 00:04:14,040 or it's in this state, which means effectively it failed. 89 00:04:14,040 --> 00:04:17,730 Now as a C++ developer, or Java developer, 90 00:04:17,730 --> 00:04:18,600 or something like that, 91 00:04:18,600 --> 00:04:22,800 you might have been tempted return null in this case 92 00:04:22,800 --> 00:04:24,600 to represent failure. 93 00:04:24,600 --> 00:04:27,420 Null is a very dangerous thing in programming. 94 00:04:27,420 --> 00:04:30,330 An option is a safe alternative 95 00:04:30,330 --> 00:04:33,150 to using raw null pointers. 96 00:04:33,150 --> 00:04:34,920 Right, when I call this function, 97 00:04:34,920 --> 00:04:37,530 I can then check the option that came back. 98 00:04:37,530 --> 00:04:39,540 Does it contain some value? 99 00:04:39,540 --> 00:04:41,070 In which case, give it to me 100 00:04:41,070 --> 00:04:43,110 or did it contain no value at all? 101 00:04:43,110 --> 00:04:45,420 So let's see how to call that function 102 00:04:45,420 --> 00:04:47,940 using the match statement to extract the value 103 00:04:47,940 --> 00:04:49,040 that it might contain. 104 00:04:50,190 --> 00:04:54,690 Right, so I've declared this here. 105 00:04:54,690 --> 00:04:59,253 My return variable if you like, of type option u32, 106 00:05:00,810 --> 00:05:02,430 I call the function, 107 00:05:02,430 --> 00:05:05,970 I pass in some hours, some minutes, some seconds. 108 00:05:05,970 --> 00:05:10,470 It'll return an option of u32 into this variable, 109 00:05:10,470 --> 00:05:14,490 which I then test, does it contain some value? 110 00:05:14,490 --> 00:05:16,180 In which case give me the value 111 00:05:17,187 --> 00:05:19,950 and it'll print out the second of the datas 112 00:05:19,950 --> 00:05:21,600 and then the result. 113 00:05:21,600 --> 00:05:22,770 Or alternatively, 114 00:05:22,770 --> 00:05:26,850 if the function returned an option in state none, 115 00:05:26,850 --> 00:05:29,460 then that indicated an error condition, really. 116 00:05:29,460 --> 00:05:32,580 So, second of day, no value, all right? 117 00:05:32,580 --> 00:05:34,950 So this is really commonly used. 118 00:05:34,950 --> 00:05:36,570 Take an option variable 119 00:05:36,570 --> 00:05:39,600 and then test to see whether it contains some value. 120 00:05:39,600 --> 00:05:41,550 Remember that was the name of the variant 121 00:05:41,550 --> 00:05:44,313 or whether it contains no value at all, none. 122 00:05:45,600 --> 00:05:47,820 Right, because options are so popular, 123 00:05:47,820 --> 00:05:49,320 there are lots and lots and lots 124 00:05:49,320 --> 00:05:51,840 and lots of functions in rust within option 125 00:05:51,840 --> 00:05:55,080 to say maybe a value, maybe not 126 00:05:55,080 --> 00:05:56,700 because it's such a common concept, 127 00:05:56,700 --> 00:05:58,230 because it's such a common requirement 128 00:05:58,230 --> 00:06:01,560 to kind of extract the value out of an option. 129 00:06:01,560 --> 00:06:03,600 There's a function called unwrap_or() 130 00:06:03,600 --> 00:06:05,580 which is really useful. 131 00:06:05,580 --> 00:06:10,580 It will internally, when you call unwrap_ or it does a test 132 00:06:10,950 --> 00:06:14,190 and if the option contains some value 133 00:06:14,190 --> 00:06:15,510 it'll give you the value 134 00:06:15,510 --> 00:06:18,690 or you can specify a default value 135 00:06:18,690 --> 00:06:22,440 that you'd like to get back in the case where it was none. 136 00:06:22,440 --> 00:06:24,120 So it would look like this. 137 00:06:24,120 --> 00:06:25,623 You'd have an option variable, 138 00:06:26,731 --> 00:06:28,740 and then you'd assign it some value 139 00:06:28,740 --> 00:06:32,280 and it will either contain some value or none. 140 00:06:32,280 --> 00:06:37,280 You can say, give me the value or give me back zero instead. 141 00:06:37,860 --> 00:06:40,980 So if it contains a value, if it contains some value, 142 00:06:40,980 --> 00:06:44,280 it'll unwrap it and give it to you as a u32. 143 00:06:44,280 --> 00:06:45,660 If it contains none, 144 00:06:45,660 --> 00:06:49,050 then you can specify what default value to get back instead. 145 00:06:49,050 --> 00:06:51,900 Okay, so this is a handy alternative 146 00:06:51,900 --> 00:06:53,700 to write in a match statement. 147 00:06:53,700 --> 00:06:55,290 Instead of you have to say, 148 00:06:55,290 --> 00:06:58,770 does it contain some value or does it contain no value? 149 00:06:58,770 --> 00:07:00,900 This does the same thing, but internally. 150 00:07:00,900 --> 00:07:02,520 Give me the value if there is one 151 00:07:02,520 --> 00:07:07,140 or give me back the value suitable default if it doesn't. 152 00:07:07,140 --> 00:07:09,720 So it turns out unwrap_or 153 00:07:09,720 --> 00:07:13,590 is just one of many functions defined in the option type. 154 00:07:13,590 --> 00:07:15,900 Technically speaking, there are lots 155 00:07:15,900 --> 00:07:18,570 and lots of methods available with the option type. 156 00:07:18,570 --> 00:07:20,280 I didn't get full details online. 157 00:07:20,280 --> 00:07:23,280 If you go into the documentation for the rust language, 158 00:07:23,280 --> 00:07:26,280 if you go into the standard crate, 159 00:07:26,280 --> 00:07:29,040 it has a module called option 160 00:07:29,040 --> 00:07:30,570 and if you click the link, 161 00:07:30,570 --> 00:07:34,500 it'll give you documentation about the option module 162 00:07:34,500 --> 00:07:36,240 in the standard crate. 163 00:07:36,240 --> 00:07:38,445 Let's have a look at this link. 164 00:07:38,445 --> 00:07:39,278 And here it is. 165 00:07:39,278 --> 00:07:42,030 So in the documentation for the rust language, 166 00:07:42,030 --> 00:07:46,140 in the standard crate, there's a module called option. 167 00:07:46,140 --> 00:07:48,420 Remember modules like in namespace. 168 00:07:48,420 --> 00:07:51,270 And in the module option, if you scroll down 169 00:07:51,270 --> 00:07:53,370 it's got some explanation here, some code, 170 00:07:54,780 --> 00:07:58,680 but it also mentions that in the option module, 171 00:07:58,680 --> 00:07:59,610 there is an enum. 172 00:07:59,610 --> 00:08:01,503 If I just click the enums link here, 173 00:08:02,460 --> 00:08:04,710 there's an enum called option. 174 00:08:04,710 --> 00:08:06,000 That's what we're talking about. 175 00:08:06,000 --> 00:08:07,260 We're talking about the option enum. 176 00:08:07,260 --> 00:08:08,380 Let's click that link 177 00:08:10,680 --> 00:08:14,223 and here it'll tell you the option enum. 178 00:08:15,390 --> 00:08:18,990 Option, with a capital letter, is an enum type 179 00:08:18,990 --> 00:08:23,990 defined in the option, lowercase, module in the stud crate. 180 00:08:24,330 --> 00:08:27,420 And this option enum is public, 181 00:08:27,420 --> 00:08:28,710 thankfully we can access it. 182 00:08:28,710 --> 00:08:30,210 It contains two variants. 183 00:08:30,210 --> 00:08:33,210 The variants are none and some, 184 00:08:33,210 --> 00:08:36,390 and these are all the methods, functions, available. 185 00:08:36,390 --> 00:08:40,290 You can call any of these methods on an option, okay? 186 00:08:40,290 --> 00:08:42,930 I'm not even gonna attempt to go through this list 187 00:08:42,930 --> 00:08:46,023 because it's very comprehensive. 188 00:08:47,790 --> 00:08:50,103 The one we looked at was this, unwrap_or. 189 00:08:51,780 --> 00:08:54,090 So the unwrap_or function. 190 00:08:54,090 --> 00:08:57,660 And without getting too, kind of, tied up in the syntax 191 00:08:57,660 --> 00:09:00,930 it returns the value if it contains some value 192 00:09:00,930 --> 00:09:04,143 or it'll return the default that you've specified. 193 00:09:05,070 --> 00:09:06,960 Okay, but there are lots of other functions as well. 194 00:09:06,960 --> 00:09:08,760 Have a look through the documentation. 195 00:09:08,760 --> 00:09:11,460 It's the kind of thing that you probably won't do initially, 196 00:09:11,460 --> 00:09:13,650 but the more you start writing rust code, 197 00:09:13,650 --> 00:09:16,350 the more you'll be looking for some functionality. 198 00:09:16,350 --> 00:09:19,740 Can the option enum do some code? 199 00:09:19,740 --> 00:09:21,450 And there were lots of functions here 200 00:09:21,450 --> 00:09:24,390 for you to, kind of, learn as time goes by 201 00:09:24,390 --> 00:09:25,623 in your rust career. 202 00:09:26,580 --> 00:09:27,660 You never learn all of it, 203 00:09:27,660 --> 00:09:30,060 but you learn the bits that you need to. 204 00:09:30,060 --> 00:09:33,120 Okay, so let's have a look at an example of all this. 205 00:09:33,120 --> 00:09:34,530 Same project as before. 206 00:09:34,530 --> 00:09:36,243 Lesson four enums. 207 00:09:37,260 --> 00:09:42,030 So we're gonna look at, in the main rs, 208 00:09:42,030 --> 00:09:45,300 we're going to look at a function that returns an enum 209 00:09:45,300 --> 00:09:50,300 sec of day and a function that calls the sec of day 210 00:09:50,580 --> 00:09:54,450 and retrieves the enum and processes it. 211 00:09:54,450 --> 00:09:56,160 Okay, so we'll talk through the code 212 00:09:56,160 --> 00:09:57,750 and then we'll run it as normal. 213 00:09:57,750 --> 00:09:59,700 Let's have a look at the code. 214 00:09:59,700 --> 00:10:01,050 Right, so here we are. 215 00:10:01,050 --> 00:10:06,050 This is the demo project, and in my main function, 216 00:10:07,140 --> 00:10:09,053 let me uncomment, demo_using_option_enum. 217 00:10:12,060 --> 00:10:12,930 Very good. 218 00:10:12,930 --> 00:10:17,673 And it is, well, these are the two functions of interest. 219 00:10:19,110 --> 00:10:21,240 There's the function that I talked about. 220 00:10:21,240 --> 00:10:24,030 You pass in hours, minute, seconds, 221 00:10:24,030 --> 00:10:26,490 it'll return, hopefully, a u32, 222 00:10:26,490 --> 00:10:28,530 maybe it'll return none. 223 00:10:28,530 --> 00:10:32,190 If the hours, minutes and seconds are valid, 224 00:10:32,190 --> 00:10:36,000 then it will return the some value. 225 00:10:36,000 --> 00:10:37,960 It'll return basically an option object 226 00:10:39,000 --> 00:10:40,710 with the flag set to some 227 00:10:40,710 --> 00:10:42,900 with the value that we've just computed 228 00:10:42,900 --> 00:10:46,080 or if hours or minutes or seconds invalid, 229 00:10:46,080 --> 00:10:47,310 then it returns none. 230 00:10:47,310 --> 00:10:50,730 Effectively the equivalent in rust of a null pointer, 231 00:10:50,730 --> 00:10:52,020 kind of. 232 00:10:52,020 --> 00:10:53,880 So that's my function. 233 00:10:53,880 --> 00:10:55,950 And then I call it up here. 234 00:10:55,950 --> 00:11:00,950 So I declare available of type, option u32. 235 00:11:01,080 --> 00:11:04,080 If I call the function with valid inputs 236 00:11:04,080 --> 00:11:06,480 then I'll get back an option 237 00:11:06,480 --> 00:11:09,660 that contains some value, okay? 238 00:11:09,660 --> 00:11:12,090 So it'll say second of day 239 00:11:12,090 --> 00:11:16,380 and it'll display the some value and I can unwrap it. 240 00:11:16,380 --> 00:11:18,930 That's basically the same as doing a match, really, 241 00:11:18,930 --> 00:11:20,610 but more concisely. 242 00:11:20,610 --> 00:11:22,950 Give me the value that it contains 243 00:11:22,950 --> 00:11:25,680 or zero if it doesn't contain a value. 244 00:11:25,680 --> 00:11:30,680 So if I pass in 23, 59, 59, that's one second to midnight. 245 00:11:33,060 --> 00:11:35,943 So just trying to do the maths here, in my head. 246 00:11:36,840 --> 00:11:40,833 I think there were, is it 86,400 seconds in a day? 247 00:11:41,820 --> 00:11:43,743 I'll see if I know it, cargo run, 248 00:11:45,570 --> 00:11:48,360 ignoring the warnings about unused functions. 249 00:11:48,360 --> 00:11:49,350 Oh, look at that. 250 00:11:49,350 --> 00:11:52,410 So if it's one second to midnight, 251 00:11:52,410 --> 00:11:57,410 then it's 86,399 seconds into the day, 252 00:11:58,350 --> 00:12:00,450 one second before the start of the next day. 253 00:12:00,450 --> 00:12:02,973 So that all worked beautifully. 254 00:12:03,900 --> 00:12:05,970 Let me change my code. 255 00:12:05,970 --> 00:12:08,820 Let me comment out the valid call 256 00:12:08,820 --> 00:12:10,710 and comment the invalid call. 257 00:12:10,710 --> 00:12:13,860 I've passed in an invalid input. 258 00:12:13,860 --> 00:12:16,710 So my function will kind of fail. 259 00:12:16,710 --> 00:12:18,150 Well, it's not gonna fail, but it'll say, 260 00:12:18,150 --> 00:12:21,120 oh, hang on, that's an invalid hour 261 00:12:21,120 --> 00:12:24,240 and it'll return an empty box, effectively. 262 00:12:24,240 --> 00:12:25,320 And option is like a box. 263 00:12:25,320 --> 00:12:26,670 It may contain a value, 264 00:12:26,670 --> 00:12:30,540 it may contain no value at all, so it returns none. 265 00:12:30,540 --> 00:12:33,720 So when I then try to pick it apart, 266 00:12:33,720 --> 00:12:36,300 the option will be none. 267 00:12:36,300 --> 00:12:40,620 And it'll say second of date, no value available there. 268 00:12:40,620 --> 00:12:43,350 And then when I try to unwrap it here, the unwrap, 269 00:12:43,350 --> 00:12:45,360 well it can't unwrap no value, 270 00:12:45,360 --> 00:12:47,220 so it'll gimme back a default value instead. 271 00:12:47,220 --> 00:12:49,980 So this default value, it's up to you what you give it. 272 00:12:49,980 --> 00:12:52,710 Zero seemed like a good default for me. 273 00:12:52,710 --> 00:12:54,410 So when I run the application now, 274 00:12:55,560 --> 00:12:56,860 that's what I'm gonna see. 275 00:12:57,930 --> 00:12:59,790 When I try to do an explicit match. 276 00:12:59,790 --> 00:13:02,910 Second of day, no value available. 277 00:13:02,910 --> 00:13:06,030 Okay, no value available, that's correct. 278 00:13:06,030 --> 00:13:08,220 And then when I try to unwrap it, 279 00:13:08,220 --> 00:13:09,870 it couldn't unwrap no value, 280 00:13:09,870 --> 00:13:12,930 so it gave me back my supplied default instead, 281 00:13:12,930 --> 00:13:14,580 which is zero. 282 00:13:14,580 --> 00:13:16,740 Okay, so option very widely used. 283 00:13:16,740 --> 00:13:20,160 We're gonna use that a lot in the course as we go through. 284 00:13:20,160 --> 00:13:22,980 And don't forget, as well as the unwrap_or method 285 00:13:22,980 --> 00:13:25,020 there's all the other methods available 286 00:13:25,020 --> 00:13:27,220 in the option type as well that you can use.