1 00:00:06,620 --> 00:00:09,120 - What we're going to look at now is a closure 2 00:00:09,120 --> 00:00:12,210 that a function, sorry, that receives an FnMut. 3 00:00:12,210 --> 00:00:14,730 So remember all of this basically centers 4 00:00:14,730 --> 00:00:17,970 on the inheritance hierarchy between these traits. 5 00:00:17,970 --> 00:00:20,160 FnOnce is the super trait. 6 00:00:20,160 --> 00:00:25,113 FnMut inherits from it and Fn inherits from that. 7 00:00:26,070 --> 00:00:28,830 So let's imagine we've got a function 8 00:00:28,830 --> 00:00:31,050 that receives that type of parameter. 9 00:00:31,050 --> 00:00:33,990 Okay? So that means you can pass in, 10 00:00:33,990 --> 00:00:36,300 you must pass in something of that type 11 00:00:36,300 --> 00:00:39,063 or something which inherits from that type, like this. 12 00:00:40,050 --> 00:00:42,200 So let's see a function that receives 13 00:00:42,200 --> 00:00:44,253 an FnMut as a parameter. 14 00:00:45,180 --> 00:00:48,300 Here's a function, I've called it receive FnMut. 15 00:00:48,300 --> 00:00:50,400 It takes a function, a mutable function, okay, 16 00:00:50,400 --> 00:00:52,470 'cause it's gonna be mutating state. 17 00:00:52,470 --> 00:00:54,300 Then you have to declare it as mutable. 18 00:00:54,300 --> 00:00:58,140 So a mutable lambda, effectively a closure. 19 00:00:58,140 --> 00:01:01,410 This F is of type FnMut. 20 00:01:01,410 --> 00:01:04,770 So it's a type constraint and it has a signature specifier. 21 00:01:04,770 --> 00:01:07,360 So it means you can basically pass in a closure 22 00:01:08,790 --> 00:01:10,890 which implements FnMut. 23 00:01:10,890 --> 00:01:12,690 So it's allowed to mutate at state, 24 00:01:12,690 --> 00:01:13,830 and the closure you pass in 25 00:01:13,830 --> 00:01:16,800 must serve no parameters and no return. 26 00:01:16,800 --> 00:01:18,753 And it calls the lambda twice. 27 00:01:19,610 --> 00:01:21,690 Okay? So whatever lambda or closure you pass in here, 28 00:01:21,690 --> 00:01:25,053 it'll call it many times and that's fine. 29 00:01:25,950 --> 00:01:28,200 So what can we pass in to this function? 30 00:01:28,200 --> 00:01:30,780 Anything which implements FnMut 31 00:01:30,780 --> 00:01:33,510 or anything which implements Fn. 32 00:01:33,510 --> 00:01:34,710 So let's see an example of that. 33 00:01:34,710 --> 00:01:37,320 In our demo project we run main, 34 00:01:37,320 --> 00:01:40,350 and we're gonna look at demo, closures, FnMut, 35 00:01:40,350 --> 00:01:42,510 and then we'll run the code. 36 00:01:42,510 --> 00:01:46,440 Right, so in our main code, I scroll down to the bottom. 37 00:01:46,440 --> 00:01:48,090 Let's comment out the bit we've done, 38 00:01:48,090 --> 00:01:50,160 and uncomment the next step. 39 00:01:50,160 --> 00:01:52,803 Demo closures of FnMut. 40 00:01:55,590 --> 00:01:56,940 Let's have a look. 41 00:01:56,940 --> 00:01:59,283 It's basically similar to what we had before, 42 00:02:00,750 --> 00:02:02,823 but not quite as flexible. 43 00:02:04,260 --> 00:02:06,330 So here's my function. 44 00:02:06,330 --> 00:02:08,880 I've passed in, it receives, 45 00:02:08,880 --> 00:02:10,710 it's a generic function again. 46 00:02:10,710 --> 00:02:14,820 It receives a generic parameter 'F', where F must be - 47 00:02:14,820 --> 00:02:19,740 when you see FnOnce or FnMut or Fn, it means closure. 48 00:02:19,740 --> 00:02:23,220 Okay? So this function you pass, that you pass in. 49 00:02:23,220 --> 00:02:26,980 This closure must be something which implements FnMut 50 00:02:28,000 --> 00:02:30,240 or a sub trait like Fn. 51 00:02:30,240 --> 00:02:32,850 Basically a closure that takes no parameters 52 00:02:32,850 --> 00:02:34,350 and doesn't return anything. 53 00:02:34,350 --> 00:02:35,400 We call the closure twice. 54 00:02:35,400 --> 00:02:37,950 Whenever closure we pass in, will be invoked twice. 55 00:02:39,450 --> 00:02:40,890 Okay? Now then. 56 00:02:40,890 --> 00:02:43,950 Because this type, this part by here 57 00:02:43,950 --> 00:02:45,740 is constrained to be FnMut, 58 00:02:45,740 --> 00:02:47,400 in the hierarchy, remember, 59 00:02:47,400 --> 00:02:51,390 we had FnOnce, then FnMut, then Fn. 60 00:02:51,390 --> 00:02:52,890 So you've gotta pass in something 61 00:02:52,890 --> 00:02:54,420 that's at least an FnMut. 62 00:02:54,420 --> 00:02:56,070 You can't pass in an FnOnce 63 00:02:56,070 --> 00:02:58,290 because that's too high in the hierarchy. 64 00:02:58,290 --> 00:03:02,100 It's like having a class A, class B, class C. 65 00:03:02,100 --> 00:03:03,690 If the function takes a B, 66 00:03:03,690 --> 00:03:05,310 you've gotta pass in at least a B 67 00:03:05,310 --> 00:03:07,560 or maybe something below it in the hierarchy. 68 00:03:08,580 --> 00:03:11,040 So I can't pass in FnOnce. 69 00:03:11,040 --> 00:03:14,490 FnOnce is above FnMut in the inheritance hierarchy, 70 00:03:14,490 --> 00:03:16,413 it's like a super class or super two. 71 00:03:16,413 --> 00:03:19,650 So I can't pass in FnOnce, okay, 72 00:03:19,650 --> 00:03:23,400 because well the closure calls this function twice. 73 00:03:23,400 --> 00:03:25,350 So if I could do this 74 00:03:25,350 --> 00:03:27,480 then it would call this closure twice 75 00:03:27,480 --> 00:03:28,650 and that would be catastrophic, 76 00:03:28,650 --> 00:03:33,120 because the, it drops the external strength, S1. 77 00:03:33,120 --> 00:03:35,460 This closure can only be invoked once, 78 00:03:35,460 --> 00:03:37,710 it's not safe to pass it into something 79 00:03:37,710 --> 00:03:40,170 that potentially might call it twice. 80 00:03:40,170 --> 00:03:42,333 So we can't pass in an FnOnce, 81 00:03:43,170 --> 00:03:46,830 but I can pass in a closure which implements FnMut. 82 00:03:46,830 --> 00:03:49,290 That's the same closure we looked at previously. 83 00:03:49,290 --> 00:03:53,880 This is my closure, which captures a mutable reference. 84 00:03:53,880 --> 00:03:55,800 It changes S2. 85 00:03:55,800 --> 00:03:58,560 So this closure will implement FnMut 86 00:03:58,560 --> 00:04:00,900 but I can pass that closure into here. 87 00:04:00,900 --> 00:04:03,870 That's exactly what this function was expecting. 88 00:04:03,870 --> 00:04:05,820 A closure that implements FnMut 89 00:04:05,820 --> 00:04:07,800 or something which inherits from that, 90 00:04:07,800 --> 00:04:10,863 such as a closure which implements just Fn. 91 00:04:11,910 --> 00:04:13,440 So you can see why in the previous section 92 00:04:13,440 --> 00:04:17,370 we discussed the concepts of FnOnce, FnMut, and Fn 93 00:04:17,370 --> 00:04:19,230 is critical really to understand this. 94 00:04:19,230 --> 00:04:20,700 Here's a closure. 95 00:04:20,700 --> 00:04:25,500 The compiler will figure out, it doesn't move state, 96 00:04:25,500 --> 00:04:29,010 it doesn't mutate state, it just captures S3 97 00:04:29,010 --> 00:04:30,750 as an immutable reference. 98 00:04:30,750 --> 00:04:34,984 So this closure will implement just the Fn trait. 99 00:04:34,984 --> 00:04:37,590 Fn inherits from FnMut. 100 00:04:37,590 --> 00:04:41,670 So it's okay to pass this into an FnMut parameter. 101 00:04:41,670 --> 00:04:44,080 Okay? So all of this will also work 102 00:04:47,640 --> 00:04:49,083 Cargo run. 103 00:04:51,930 --> 00:04:54,910 Okay, so in my demo of closures for FnMut 104 00:04:56,070 --> 00:04:59,550 I called the receive mut, FnMut function. 105 00:04:59,550 --> 00:05:01,260 I gave it a closure. 106 00:05:01,260 --> 00:05:03,260 My original string was B, B, B 107 00:05:04,350 --> 00:05:08,820 but the closure mutates it and that closure remember, 108 00:05:08,820 --> 00:05:11,310 whatever closure I pass in here 109 00:05:11,310 --> 00:05:13,860 gets passed in as the parameter. 110 00:05:13,860 --> 00:05:16,740 That's the function that gets called twice. 111 00:05:16,740 --> 00:05:18,960 So it'll invoke my closure twice. 112 00:05:18,960 --> 00:05:23,370 So it invokes my closure the first time to append B, B, B. 113 00:05:23,370 --> 00:05:25,830 And then it calls it the second time 114 00:05:25,830 --> 00:05:27,870 to append B, B, B a second time. 115 00:05:27,870 --> 00:05:29,908 So you can see it has mutated it. 116 00:05:29,908 --> 00:05:34,680 And then finally when I pass in my immutable closure here, 117 00:05:34,680 --> 00:05:36,842 my Fn closure again that closure 118 00:05:36,842 --> 00:05:40,800 will get passed in to the parameter 119 00:05:40,800 --> 00:05:43,800 as a function and it calls that function twice as well 120 00:05:43,800 --> 00:05:46,473 which prints out C, C, C twice. 121 00:05:48,420 --> 00:05:50,760 Okay, so the third example we're going to look at 122 00:05:50,760 --> 00:05:54,270 is closures which implement the, 123 00:05:54,270 --> 00:05:58,170 or functions that take an Fn trait. 124 00:05:58,170 --> 00:06:00,600 So let's see that. 125 00:06:00,600 --> 00:06:03,513 If a function calls a closure many times, 126 00:06:04,530 --> 00:06:06,360 and if you want to allow the closure 127 00:06:06,360 --> 00:06:07,590 to capture state immutably, 128 00:06:07,590 --> 00:06:09,870 you're not gonna change it, you're just going to read it, 129 00:06:09,870 --> 00:06:12,570 then your function should basically take a parameter 130 00:06:12,570 --> 00:06:14,790 of type Fn like this. 131 00:06:14,790 --> 00:06:17,190 I've gotta function called receive Fn. 132 00:06:17,190 --> 00:06:19,890 It receives a parameter, a function, 133 00:06:19,890 --> 00:06:24,090 well a parameter of type F where F is a closure, 134 00:06:24,090 --> 00:06:27,000 no parameters, no return value, 135 00:06:27,000 --> 00:06:29,970 basically a closure that doesn't mutate the state. 136 00:06:29,970 --> 00:06:31,830 So again, the important thing 137 00:06:31,830 --> 00:06:35,610 is the inheritance hierarchy of traits 138 00:06:35,610 --> 00:06:38,237 for functions of closures. 139 00:06:38,237 --> 00:06:40,140 FnOnce at the top. 140 00:06:40,140 --> 00:06:45,140 FnMut inherits from it and Fn inherits from that. 141 00:06:45,210 --> 00:06:49,290 So if you have a function that's basically taken an Fn, 142 00:06:49,290 --> 00:06:50,703 you can only pass in that. 143 00:06:51,990 --> 00:06:54,990 Okay? You can't pass in one of those or one of those. 144 00:06:54,990 --> 00:06:57,150 It has to be basically a function 145 00:06:57,150 --> 00:06:59,730 like that that gets passed in. 146 00:06:59,730 --> 00:07:02,400 So let's see how we can call this function 147 00:07:02,400 --> 00:07:06,183 and pass in a closure, which implements just the Fn trait. 148 00:07:07,350 --> 00:07:09,930 You can pass in a closure that implements the Fn trait. 149 00:07:09,930 --> 00:07:11,460 Let's see how to do it. 150 00:07:11,460 --> 00:07:13,647 In our code demo closes Fn, 151 00:07:13,647 --> 00:07:16,650 and this would be our last demo for this lesson. 152 00:07:16,650 --> 00:07:17,730 It's been quite a journey, hasn't it? 153 00:07:17,730 --> 00:07:21,060 So let's run the program when we finish looking at the code. 154 00:07:21,060 --> 00:07:24,390 So in our main code, this is the demo. 155 00:07:24,390 --> 00:07:27,003 Demo closures, Fn do it, 156 00:07:28,867 --> 00:07:31,620 which is here. 157 00:07:31,620 --> 00:07:35,340 So I've got a function which receives some kind of, 158 00:07:35,340 --> 00:07:37,650 it's a generic, it receives some kind of parameter 159 00:07:37,650 --> 00:07:41,580 of type F where F is a closure, 160 00:07:41,580 --> 00:07:44,340 which implements the Fn trait. 161 00:07:44,340 --> 00:07:46,080 So it captures state immutably 162 00:07:46,080 --> 00:07:48,180 or it doesn't capture state at all. 163 00:07:48,180 --> 00:07:49,320 That would also work. 164 00:07:49,320 --> 00:07:51,570 And then it calls the function several times. 165 00:07:52,830 --> 00:07:55,860 Okay? So if you have a function that receives an Fn, 166 00:07:55,860 --> 00:07:59,490 remember the hierarchy, we have FnOnce at the top, 167 00:07:59,490 --> 00:08:00,930 below it we have FnMut. 168 00:08:00,930 --> 00:08:02,370 And then below that we have Fn. 169 00:08:02,370 --> 00:08:04,440 Fn is at the bottom of the hierarchy. 170 00:08:04,440 --> 00:08:07,740 So you must just be able to pass in an Fn parameter. 171 00:08:07,740 --> 00:08:10,800 You can't pass in an FnOnce, okay? 172 00:08:10,800 --> 00:08:13,530 Because that is above Fn in the hierarchy. 173 00:08:13,530 --> 00:08:16,710 You've gotta pass in an Fn, not an FnOnce. 174 00:08:16,710 --> 00:08:19,140 You can't pass in an FnMut either. 175 00:08:19,140 --> 00:08:22,020 So this closure here, 176 00:08:22,020 --> 00:08:23,040 same closure as before. 177 00:08:23,040 --> 00:08:24,840 You can't pass that in either. 178 00:08:24,840 --> 00:08:28,050 You can only pass in something that doesn't move the data. 179 00:08:28,050 --> 00:08:31,890 So it's not an FnOnce and it doesn't retake the data. 180 00:08:31,890 --> 00:08:33,420 So it's not an FnMut. 181 00:08:33,420 --> 00:08:36,660 It must be something that just captures the state immutably. 182 00:08:36,660 --> 00:08:39,810 Okay? So here's a closure 183 00:08:39,810 --> 00:08:41,730 which captures the state immutably. 184 00:08:41,730 --> 00:08:44,059 This closure will be converted into a structure 185 00:08:44,059 --> 00:08:47,250 which implements Fn, the Fn trait. 186 00:08:47,250 --> 00:08:49,020 And that's exactly what this function 187 00:08:49,020 --> 00:08:50,850 was designed to receive. 188 00:08:50,850 --> 00:08:54,000 Receive Fn is meant to receive a closure, 189 00:08:54,000 --> 00:08:55,953 which just implements the Fn trait. 190 00:08:57,960 --> 00:08:59,550 So that'll get passed into here 191 00:08:59,550 --> 00:09:00,960 and then it'll close the function. 192 00:09:00,960 --> 00:09:02,660 Call a function a couple of times. 193 00:09:08,160 --> 00:09:09,243 Okay, 194 00:09:11,100 --> 00:09:11,933 so there we go. 195 00:09:11,933 --> 00:09:15,090 So there are lots of functions in the standard library 196 00:09:15,090 --> 00:09:16,560 that receive closures. 197 00:09:16,560 --> 00:09:19,980 Whenever you see a function, a generic function, 198 00:09:19,980 --> 00:09:22,200 where the generic parameter is constrained 199 00:09:22,200 --> 00:09:26,010 to be FnOnce or FnMut or Fn, 200 00:09:26,010 --> 00:09:28,500 it means you can pass in a closure. 201 00:09:28,500 --> 00:09:31,110 and depending on whether the type parameter 202 00:09:31,110 --> 00:09:36,110 specifies Fn or FnMut or FnOnce, 203 00:09:39,060 --> 00:09:41,070 depending on the type constraint, 204 00:09:41,070 --> 00:09:43,470 you can either pass in a closure 205 00:09:43,470 --> 00:09:47,730 that moves state into the closure, 206 00:09:47,730 --> 00:09:51,813 or a closure that captures mutably the state, 207 00:09:52,680 --> 00:09:56,610 or a closure that captures immutably the state. 208 00:09:56,610 --> 00:09:57,693 So it's quite tricky. 209 00:09:58,560 --> 00:10:00,891 Nobody ever said this was gonna be easy. 210 00:10:00,891 --> 00:10:03,870 It was something that took me a while to figure out 211 00:10:03,870 --> 00:10:05,100 because I've been working in Java 212 00:10:05,100 --> 00:10:06,840 and C sharp and C plus plus for many years 213 00:10:06,840 --> 00:10:09,330 and you kind of know what to expect. 214 00:10:09,330 --> 00:10:12,575 And the closure model, like Lambdas in Rust 215 00:10:12,575 --> 00:10:15,575 is really quite complex. 216 00:10:15,575 --> 00:10:18,330 But have a play with these examples. 217 00:10:18,330 --> 00:10:19,770 Try commenting bits of code out 218 00:10:19,770 --> 00:10:21,900 and add commenting and see what errors you get 219 00:10:21,900 --> 00:10:23,490 and that'll help you understand 220 00:10:23,490 --> 00:10:26,730 the mechanism that Rust is providing for you. 221 00:10:26,730 --> 00:10:28,180 And it's really quite clever.