1 00:00:00,105 --> 00:00:02,772 (upbeat music) 2 00:00:05,366 --> 00:00:06,199 Frank: In the last video, 3 00:00:06,199 --> 00:00:09,240 we learned about stateless Lambda expressions. 4 00:00:09,240 --> 00:00:12,570 That is, Lambda expressions that capture no information 5 00:00:12,570 --> 00:00:13,720 from their environment. 6 00:00:14,640 --> 00:00:17,280 In this video, we'll learn about their close relative, 7 00:00:17,280 --> 00:00:19,740 the stateful Lambda expression. 8 00:00:19,740 --> 00:00:23,070 That is, a Lambda expression that does capture information 9 00:00:23,070 --> 00:00:24,750 from its environment. 10 00:00:24,750 --> 00:00:27,600 It's important to note that stateful Lambda expressions 11 00:00:27,600 --> 00:00:30,240 are just like stateless Lambda expressions 12 00:00:30,240 --> 00:00:33,030 except they have non-empty capture lists. 13 00:00:33,030 --> 00:00:35,040 So everything we do with a stateless Lambda, 14 00:00:35,040 --> 00:00:37,530 we can do with a stateful Lambda and more. 15 00:00:37,530 --> 00:00:40,350 So what exactly do we mean when we refer to a Lambda 16 00:00:40,350 --> 00:00:42,810 capturing information from its environment 17 00:00:42,810 --> 00:00:45,060 and how is it able to do this? 18 00:00:45,060 --> 00:00:46,530 Well, what we're referring to 19 00:00:46,530 --> 00:00:48,840 is the Lambda's ability to use variables 20 00:00:48,840 --> 00:00:51,270 declared within its reaching scope 21 00:00:51,270 --> 00:00:55,230 without having to pass them into the Lambda as parameters. 22 00:00:55,230 --> 00:00:57,840 This is accomplished by simply listing the variables 23 00:00:57,840 --> 00:01:01,350 we would like the Lambda to use within its capture list. 24 00:01:01,350 --> 00:01:02,400 Pretty cool, right? 25 00:01:02,400 --> 00:01:03,900 But how does it work? 26 00:01:03,900 --> 00:01:05,730 Well, to fully understand this, 27 00:01:05,730 --> 00:01:08,100 we first need to take a look under the hood 28 00:01:08,100 --> 00:01:11,043 to see what happens when a Lambda expression is compiled. 29 00:01:12,330 --> 00:01:13,620 Here, we can see a simple 30 00:01:13,620 --> 00:01:16,470 stateless Lambda expression defined. 31 00:01:16,470 --> 00:01:17,640 To represent the Lambda, 32 00:01:17,640 --> 00:01:21,240 the compiler generates what's known as a closure type class 33 00:01:21,240 --> 00:01:24,000 with a default constructor and an operator function 34 00:01:24,000 --> 00:01:26,160 implementing the logic of the Lambda. 35 00:01:26,160 --> 00:01:29,100 The class isn't generated until compile time 36 00:01:29,100 --> 00:01:32,610 so it might now be clear why the auto keyword must be used 37 00:01:32,610 --> 00:01:35,737 as a specifier for the type in Lambdas. 38 00:01:35,737 --> 00:01:37,950 It's because when we define Lambda expressions, 39 00:01:37,950 --> 00:01:39,933 the type hasn't been generated yet. 40 00:01:40,800 --> 00:01:44,100 The type is only generated when the lambda is compiled 41 00:01:44,100 --> 00:01:47,010 and so of course can only be assigned by the compiler 42 00:01:47,010 --> 00:01:48,330 at compile time. 43 00:01:48,330 --> 00:01:50,280 With this in mind, can you see what's happening 44 00:01:50,280 --> 00:01:53,160 when we assign a Lambda expression to a variable? 45 00:01:53,160 --> 00:01:55,980 what we're actually doing is instantiating an object 46 00:01:55,980 --> 00:01:58,440 of the compiler generated closure 47 00:01:58,440 --> 00:02:01,260 by making a call to its constructor. 48 00:02:01,260 --> 00:02:03,120 Hopefully now you'll have a better understanding 49 00:02:03,120 --> 00:02:05,490 of how Lambdas operate behind the scenes, 50 00:02:05,490 --> 00:02:06,840 but that still leaves the question 51 00:02:06,840 --> 00:02:09,870 of how they can capture information from their environment 52 00:02:09,870 --> 00:02:11,970 using the capture list. 53 00:02:11,970 --> 00:02:14,160 As the challenge, pause the video now 54 00:02:14,160 --> 00:02:15,360 and see if you can figure it out 55 00:02:15,360 --> 00:02:18,090 with your new knowledge of how Lambdas work. 56 00:02:18,090 --> 00:02:19,800 When you're done, unpause the video 57 00:02:19,800 --> 00:02:21,900 and we'll go through it in the next slide. 58 00:02:25,830 --> 00:02:28,110 If you thought of storing the captured variables 59 00:02:28,110 --> 00:02:31,560 as member variables of the compiler generated closure, 60 00:02:31,560 --> 00:02:33,690 then you are absolutely right. 61 00:02:33,690 --> 00:02:36,330 When defining a stateful Lambda's capture list, 62 00:02:36,330 --> 00:02:38,940 we're defining the parametrized constructor 63 00:02:38,940 --> 00:02:42,300 of the Lambda's compiler generated closure. 64 00:02:42,300 --> 00:02:45,420 When the stateful Lambda expression is instantiated, 65 00:02:45,420 --> 00:02:47,700 a unique function object is created 66 00:02:47,700 --> 00:02:50,100 using the parameterized constructor 67 00:02:50,100 --> 00:02:53,913 which stores the captured variables as member variables. 68 00:02:54,750 --> 00:02:57,720 We can see this being done in the example. 69 00:02:57,720 --> 00:03:00,390 A simple stateful Lambda expression is defined 70 00:03:00,390 --> 00:03:02,730 which captures the local variable y 71 00:03:02,730 --> 00:03:05,580 and takes a single parameter x. 72 00:03:05,580 --> 00:03:08,040 The compiler generates a closure for the Lambda 73 00:03:08,040 --> 00:03:10,110 with a parameterized constructor 74 00:03:10,110 --> 00:03:13,350 that takes as its parameter the variable y 75 00:03:13,350 --> 00:03:16,710 and assigns it to the closure's member variable y. 76 00:03:16,710 --> 00:03:18,630 You'll notice that the generated closure 77 00:03:18,630 --> 00:03:19,860 has an operator function 78 00:03:19,860 --> 00:03:23,190 implementing the logic of the Lambda as we would expect. 79 00:03:23,190 --> 00:03:26,520 However, this time, it's a constant member function. 80 00:03:26,520 --> 00:03:28,380 This means that no member variable 81 00:03:28,380 --> 00:03:31,980 of the instantiated object can be modified by this function 82 00:03:31,980 --> 00:03:35,970 and so the member variable y cannot be modified. 83 00:03:35,970 --> 00:03:38,430 The reason for this is because by default, 84 00:03:38,430 --> 00:03:42,783 all variables captured by value are captured by const value. 85 00:03:43,650 --> 00:03:45,930 As you can imagine, this can be quite restricting 86 00:03:45,930 --> 00:03:48,600 when we're trying to implement certain functionalities. 87 00:03:48,600 --> 00:03:52,020 So C++ provides us with a multitude of ways 88 00:03:52,020 --> 00:03:54,210 in which we could capture variables. 89 00:03:54,210 --> 00:03:56,280 Let's take a look at them. 90 00:03:56,280 --> 00:03:57,750 As seen in the last example, 91 00:03:57,750 --> 00:04:00,030 the first way in which a Lambda expression 92 00:04:00,030 --> 00:04:02,760 can capture a variable is by value. 93 00:04:02,760 --> 00:04:04,890 This is the default capturing mode, 94 00:04:04,890 --> 00:04:06,120 and so it can be accomplished 95 00:04:06,120 --> 00:04:07,950 by simply listing the variable's name 96 00:04:07,950 --> 00:04:10,500 in the Lambda's capture list. 97 00:04:10,500 --> 00:04:12,120 It's important to remember 98 00:04:12,120 --> 00:04:14,220 that a variable being captured by value 99 00:04:14,220 --> 00:04:17,190 is actually being captured by const value 100 00:04:17,190 --> 00:04:20,370 so it won't be modifiable within the Lambda. 101 00:04:20,370 --> 00:04:22,920 But what if we want to capture a variable by value 102 00:04:22,920 --> 00:04:24,813 and modify it within the Lambda? 103 00:04:26,730 --> 00:04:29,160 In that case, we can use the keyword mutable 104 00:04:29,160 --> 00:04:30,930 to tell the compiler to generate 105 00:04:30,930 --> 00:04:33,030 the Lambda's operator function 106 00:04:33,030 --> 00:04:35,910 as a non-const member function. 107 00:04:35,910 --> 00:04:39,090 By doing so, we can capture variables by value 108 00:04:39,090 --> 00:04:41,073 and modify them within the Lambda. 109 00:04:42,090 --> 00:04:43,050 As you might have guessed, 110 00:04:43,050 --> 00:04:46,170 we can also capture variables by reference. 111 00:04:46,170 --> 00:04:48,450 In this case, any changes made to a variable 112 00:04:48,450 --> 00:04:50,700 captured by reference within the Lambda 113 00:04:50,700 --> 00:04:53,820 will be visible outside the Lambda. 114 00:04:53,820 --> 00:04:55,350 Using both capturing modes, 115 00:04:55,350 --> 00:04:57,180 we can define a Lambda's capture list 116 00:04:57,180 --> 00:05:00,240 any number of ways for any number of variables. 117 00:05:00,240 --> 00:05:03,960 But what if we want to capture a large number of variables, 118 00:05:03,960 --> 00:05:06,450 but we don't want to have to list each variable? 119 00:05:06,450 --> 00:05:07,743 How do we do this? 120 00:05:09,390 --> 00:05:12,090 This is where default captures come in. 121 00:05:12,090 --> 00:05:13,830 A default capture allows a Lambda 122 00:05:13,830 --> 00:05:16,980 to capture all variables referenced within its body 123 00:05:16,980 --> 00:05:19,233 according to the defined capture mode. 124 00:05:20,610 --> 00:05:24,120 An equal sign positioned first in the Lambda's capture list 125 00:05:24,120 --> 00:05:26,040 denotes that all referenced variables 126 00:05:26,040 --> 00:05:27,873 should be captured by value. 127 00:05:29,280 --> 00:05:31,620 An ampersand denotes that they should be captured 128 00:05:31,620 --> 00:05:32,793 by reference. 129 00:05:33,780 --> 00:05:35,730 And if we use the this keyword, 130 00:05:35,730 --> 00:05:38,400 this denotes that the referenced member variables 131 00:05:38,400 --> 00:05:41,250 of the current object Lambda as defined within 132 00:05:41,250 --> 00:05:43,353 should be captured by reference. 133 00:05:45,180 --> 00:05:47,340 When implementing default captures, 134 00:05:47,340 --> 00:05:49,980 we can also explicitly capture variables 135 00:05:49,980 --> 00:05:52,740 according to different capture modes. 136 00:05:52,740 --> 00:05:54,660 It's important to note that when we do so, 137 00:05:54,660 --> 00:05:57,120 we must always place the default capture 138 00:05:57,120 --> 00:05:59,190 first in the capture list. 139 00:05:59,190 --> 00:06:00,750 Also, the explicit capture 140 00:06:00,750 --> 00:06:03,120 cannot be the same as the default. 141 00:06:03,120 --> 00:06:05,043 Otherwise, the Lambda won't compile. 142 00:06:06,000 --> 00:06:08,550 With so many possible combinations of default 143 00:06:08,550 --> 00:06:11,850 and explicit parameters, it's hard to cover them all, 144 00:06:11,850 --> 00:06:13,440 but what we've covered should prepare you 145 00:06:13,440 --> 00:06:14,580 for most situations 146 00:06:14,580 --> 00:06:17,130 in which you'll need to use stateful Lambdas. 147 00:06:17,130 --> 00:06:19,683 Now, let's head over to the IDE and implement some.