Hello, everyone.
Welcome back.
I am in the Section 21 workspace and I'm in the Stateless Lambda Project.
In this project I've got some examples of stateless lambdas that I'm using in different ways, and I've
got some using value parameter as a reference parameter as passing objects and returning lambdas and
so forth.
So I'll go through them one at a time and I've already gone ahead and built and run.
So you can see the run over here on the right.
And I'm just going to walk through this.
There are seven little test functions that I've written, that kind of exercise, a whole bunch of different
combinations of stateless lambdas.
So you can get a pretty good feel for them.
But before I talk about those little functions, let's talk about what's going on here.
So it's important to keep in mind that we are working with stateless lambda expressions.
So that means that the capture lists are empty, they're going to be empty.
For all of the examples in here, you can see here that I've included IO stream, string and vector.
These are just common includes that I'm going to use throughout.
I'm also including algorithm which gives us the standard template library algorithms and here is the
functional header.
This is the one we need for function and this is the one I mentioned in the slides in the previous lecture.
So those are my includes and here have defined a real simple class person and this is the one that I'm
going to use in some of the examples where we're passing objects within the Lambdas.
So here's my class person.
I have a friend function that's just my overloaded insertion operator that lets us display these person
objects to a stream and you can see it implemented down here.
Nothing new.
This is all stuff we have already done before.
You can see that the person class has these two attributes a name which is a string and the person's
age really simple.
We've got a constructor that expects a name and an age.
We've got a copy constructor, we've got a destructor, which I'm just letting the compiler create the
default for me, since there's nothing special to do here.
And then right here I've got my getters in my setters, right?
So I'm going to I've got my name, set name, get age, set age.
Okay.
So now that that's out of the way, you can see it's really straightforward.
I'll refer back to this when we get to it.
You can see down here in my main, what I'm doing is I'm calling these functions all the way from test
one, all the way to test seven.
So I'm going to walk through them one at a time and each one adds a little bit and changes a little
bit just so you can get a good feel for the differences between the stateless lambda expressions that
I'm going to show you.
All right.
So let me start with test one and I'm going to scroll up to it and here is test one.
And you can see over here and the output right up here, that's the output for test one.
So that's what I'll be referring to as I walk through this.
Real simple.
We have no capture list.
None of these guys are capturing anything.
That's why they're stateless.
We have no parameters and the body of the lambda just says, see out high in this case.
So it's just going to display.
Hi, we are instantiating it right there.
It's really important that we use that.
Otherwise it's not doing anything at this point.
Now that lambda expression will execute and high is displayed, you can see it right there.
Same idea with this guy here.
Except now we've got a parameter.
We've got an integer parameter x again, stateless, right?
So this is a parameter X and we are displaying X, that's the body of the lambda.
So whatever value is in here will be displayed here when we display the output statement.
Now same idea over here.
We're calling that lambda and we're passing in 100.
This 100 is being passed in here.
Right.
So now X gets the 100.
And when this body executes, we're going to display 100.
And that's exactly what's happening here.
All right.
So let's look at the third example.
Same idea, except now I've got two parameters.
I've got an X and a Y.
So we're displaying the X plus the Y over here.
We're just adding them up.
We're displaying the sum.
You see, the 100 is being passed over here to the X, the 200 is being passed into the Y.
All this is happening by value, right?
There's no references in here.
This is by value.
So we're doing copies.
And what we're going to do is 100 plus 200 and this guy will display 300.
And that's what you're seeing right here.
So that's a real, real simple example of lambda expressions.
Simple, but very useful, right?
You can see it's kind of silly.
Well, why would you do this?
You know, you just it's kind of contrived, if you will, and nobody really writes lambda expressions
this way.
It's more of what I'm going to show you in a little bit, but this gives you a good feeling for the
structure and the syntax of the lambda expressions.
They're not complicated.
You've got the capture list, you've got the parameter list, you've got the body of the lambda.
That's what it's like.
It can get more complicated and what we're doing captures and we'll do that in the next video.
So let me show you now test to let me close this piece down.
And here I've got test two and you can see here what I'm doing is using values and references now for
the parameter.
So it's going to be a little bit different because we're going to be using reference parameters in this
case.
I've got a variable here.
What I'm doing over here is I've got a lambda expression and I'm assigning that land expression to a
variable.
This is the same thing as saying something like X equals three plus five.
I'm evaluating that expression and assigning it to x.
Later on, when I use x, I'm going to be using eight.
Right?
This is exactly the same idea.
This is a variable l one.
What's important here is I'm using the auto keyword to tell the compiler, hey, compiler, you figure
out what the type of this thing is.
It's a lambda.
It's not an end, it's not a void, it's not a double, it's a lambda.
Let the compiler figure out how to do it.
Same idea.
It's the same lambda as before.
Notice the difference though.
We don't have that piece at the end, right?
So what we're doing is we're creating that lambda expression and we're assigning it to L one now whenever
I want to call it now, I could just say L one with the parents.
It looks just like a function call and essentially it is.
Remember we talked about overloading the function call operator Well, that's really what's happening
behind the scenes.
So at this point, right here, not here, but right there on line 45, that's when we get the high
here.
So hopefully that's clear.
And in this case now let's look at lines 47, 48.
We have two integers, number one and number two, and each one is been initialized to 100.
I'm creating another variable L two right here, which is also a lambda right.
Again, stateless.
I've got two parameters by value and I'm doing the same thing.
X plus y.
Set an example I used earlier, but now look what I'm doing.
I'm calling it some pass l two and then I'm passing at ten and a 20.
So the ten gets over here and the 20 comes over here.
This guy is going to be 30 and that's what's going to display right here.
We get that 30 displayed.
Now, those are two integer literals and that's perfectly valid in this case.
We've got number one.
Number two.
So now we're going to pass in instead of ten and 20, 101 hundred.
Right?
So we're going to display 200, which is what's being displayed here.
Remember, this is passed by value.
This is your value parameter.
So we're making copies of these values.
So now let's take a look at an example with some references.
And now we are right here on line 54 and we've got the same idea.
I've got a variable L three and we've got two parameters.
Now the difference is now X is a reference parameter.
We know what those are, right?
We've talked about them already in the class.
It's basically an alias to an actual parameter and I have Y, which is a value type parameter.
And all this lambda does, it's going to display X and then it's going to display Y.
But within the body of the lamb that we're changing X and Y.
Now, this is really important to understand.
When I'm changing X, I've got a reference.
So that means that the actual parameter is going to be changed to 1000.
When I change Y to 2000, the local copy of y will be changed.
So not the actual.
So let me show you what that looks like when I call this.
So at this point, remember, we're going to call this with number one and number two, and if you remember
number one and number two or 100 each.
Right?
So what's going to happen is actually let me clear this up and do this one more time.
So it's clearer.
I've got number one and number two, which is each 100.
Now I'm going to call L three with number one and number two.
Number two is 100.
So that becomes the Y.
And that's copied.
But number one is a reference, right?
So what happens is this guy now refers to the actual parameter up here.
This guy is just local.
That's really important.
It's a very important distinction.
We learned about this when we used functions exactly the same thing.
So at this point, we're going to execute this code.
This code is going to change.
First of all, it's going to display X and Y, which are 101 hundred.
Right.
Because I haven't changed them.
You can see it right there.
Then it's going to change X to 1000.
That's this guy right here.
So this guy is going to be 1000.
He's going to change Y to 2000, which is this guy.
It's irrelevant because that's going to go away when the -- is finished.
Now we're done.
So what happens is all of this gets cleaned up and the only thing that's left behind is this guy is
1000.
Number one is 1000, number two is 100.
So when we come back, we're just going to display number one and number two.
And you can see right here, we're getting the 1000, which we changed and the 100.
Okay.
Hopefully that's pretty clear.
If not, just walk through it yourself, just like I did.
And that way you'll get a really, really good feeling of what's going on here.
Okay, so let's move on to test three.
All right.
So what are we doing in test three?
We're basically doing the same thing we did in Test two, except we're using objects now instead of
primitive types.
The other example, we used integers.
So what's going on here?
Well, I'm going to create a person object called stooge, and that would be Larry and Larry's 18 years
old.
And then I want to display Stooge here, so run on line 68.
I'm in test three.
This is what's happening right there.
That one line is executing.
Larry, 18, just what we expect.
Now I'm creating a lambda.
I'll call it L four.
In this example, here we are passing in a person object.
This is really important.
This is by value.
So what happens here?
A copy.
And how do we copy objects?
Copy constructor.
The copy constructor will be called and it will create a new copy of that object.
That copy of the object will be alive within the body of the lambda.
We can change it all we want in there and it's not going to affect the actual.
That's really important.
Same thing that it's happened with integers, but now we're dealing with objects.
So now what am I passing into L for stooge?
So now what's happening is I get a new version, right?
A new copy of that stooge object.
So inside this function here I have P and P would be Larry 18, which is totally separate from this.
Larry.
18.
This is a new copy and that's active.
So I'm going to display it and it's going to display right there.
That's the second display statement, right?
The first one was up here.
And that's it.
Stooge did not change.
It can't change because we made a copy of it.
Now let's do it by reference and see the difference.
I'm right here on line 75.
Remember, we've already executed that one and we've executed that statement right over here.
So now I'm over here.
L five again.
Stateless.
One parameter.
A reference parameter.
Really, really different now, right?
No copy.
Constructor, no copy.
We're going to get an alias at this point.
We also said it's const.
So if we try to change that P object and here in the body, we won't be allowed.
The compiler will give us an error.
So let's do this.
L five We're going to pass in stooge.
We don't make a copy of it.
This P refers to the real one.
So again, very efficient.
I can't change it because it's const.
So I get the best of both worlds, right?
When I'm in here, I'm displaying p.
P is right there, Larry 18.
And you can see that third statement executes right there.
So that's passed by reference.
Now let's do pass by reference, but actually modify the object.
And that's what this last statement here does.
And let me scroll up just a little bit so you can see it a little bit better.
So remember, at this point, we've done this, this, this, and we are right here now.
So my lambda variable is l six.
I'm passing in a person object by reference.
Really important notice there's no contact over here like there was over here.
I'm able to modify that and I'm going to modify that.
So I'm going to pass in stooge.
This P will be stooge, right?
So it's going to be a reference to stooge and it's defined up there.
It scrolled off, but it was stooge and it was Larry 18.
That's my object.
But now look what I'm doing in the body.
I'm saying, hey, set the name to Frank.
So I'm changing Larry to Frank and change the age to 25.
So I'm changing the 18 to a 25, then I'm displaying P well, p is a reference to this guy, right?
And notice right there what happens.
Frank 25 Then once I finish, I'm going to display Stooge now.
Well, that is stooge, right?
So I'm going to get the same thing.
So there's proof here in both cases, there's the proof that we actually changed that stooge variable
out there from within the lambda because of that reference parameter.
Okay.
So this fit is getting a bit long now.
So what I'm going to do is I'm going to stop this video here and we'll continue with test for in the
next video.
I'll see you there.