Okay.
Welcome back.
In this video, we'll finish off what we started in the previous video.
So let's get a little bit more complicated now.
Look at a couple more examples.
I'm going to reduce this a little bit here.
All right, so here's test four and I've got two pieces to test for it and expand them both and I'll
walk through them.
The first one I've written a function and that function is called filter vector.
It's right here.
It returns nothing.
And what does it expect?
It expects a stood vector of integers and its const.
So I cannot modify it from in here.
It's called VEC and a function that's a function object.
What does that function object?
Expect an integer.
What does it return?
A boolean?
That's what the syntax says.
I know the syntax may look a little wonky, but it's just a matter of getting used to it.
It's not complicated.
And what is the name of that parameter func?
This is a function object.
So I can call that function object simply by saying func and passing an integer into it.
Any kind of integer, whether it's a literal or a variable name.
And this guy will return a boolean that I can use.
So that's what's really happening here.
I'm displaying the left bracket and then I've got a range based for loop here that's looping over this
vector.
And for each integer I in the vector, I'm calling func and passing it in.
What does this func do?
I have no idea.
That's the real power here.
I could care less what is happening in that function.
All I know is that I'm a filter vector function and I get a function.
I'm calling that function.
I really don't know what it does.
I don't care what it does.
The only thing that's important is that it expects an INT and returns a boom.
So in this case, if it returns true, I'm going to display that value and then I'm just closing this
with a bracket.
So it'll make sense now when you see when I call it.
So let me scroll up just a little bit.
I'm right here on test four, so I'm saying that's four.
That's right here.
Here's my vector of numbers called nums and I'm going to call filter vector and I'm going to pass in
nums.
Right.
That's this guy.
And now I'm going to pass in the function that I want called every time in here.
Well, I'm going to pass in a lambda expression, stateless.
It expects an INT and it returns a boolean.
That's exactly what we set up here.
So what is this guy going to do?
It's going to return true when X is greater than 50.
And this guy here will be true only whenever each one of those eyes is greater than 50.
So what does this do?
This only prints out values that are greater than 50 right there.
60, 70, 89, 80, 100.
In this example, I'm just using a different lambda.
I'm only going to display values that are less than or equal to 30.
And you can see them display right here.
And in this case, I'm only displaying values that are greater than or equal to 30 and less than or
equal to 60.
So we're displaying 30, 40, 50, 60.
This is pretty cool.
I think you can really wrap your head around this and see how powerful these lambdas are.
Also, it's very important to understand is the programmer that wrote this function doesn't really care
what this function does right here, for example, only greater than 50, less than or equal to 30.
It's up to perhaps another programmer that's using this filter vector function to decide what's the
logic here?
Now, this guy right here is called a predicate Lambda.
And I mentioned that in the slides in the previous lecture.
This is a predicate, Lambda, because it expects one or more parameters and returns a boolean.
That's the definition of a predicate lambda or a predicate function, if you will.
So again, walk through this example and try them out and change these lambdas to do different things.
And you can see just how powerful this really is.
There are so many algorithms in the standard template library that use these predicate lambdas just
like this.
So from a programmers perspective, we're working in here, right?
But the person or the team that wrote those algorithms are expecting this kind of thing and they could
care less how we want to sort something or how we want to compare something.
That's for our logic.
Determine.
Try one more.
Oh, and by the way, I should mention this line 95 right here, we use this in C++ 14 or higher in
C++ 20, we can replace this with just this auto func and let the compiler figure out that it returns
a boolean and expects an integer parameter.
So that's pretty cool too, but that's what that would be in C++ 20.
Scroll this up as well.
So now we're in test five and it's these two pieces right here.
All right.
So what's going on in test five?
Well, test five is a little bit different as well.
And you'll see this make more sense when we talk about stateful lambdas in the next couple of sections.
But in this case, look what I've got.
I've got a function called make lambda.
And what does it return auto?
Let the compiler figure it out.
It's returning a lambda.
You can see right here it's return.
There's my capture list, no parameters and there's the body of the a c statement.
Wow.
You know, you wrap your head around this thing and you're going, well, what's going on here?
Well, I'm calling a function that's returning a lambda.
It's not executing that lambda, it's just returning the lambda later on.
I can execute that lambda if I want.
And that's what I'm doing right here.
You can see right here I'm displaying test five right there.
Then I'm calling make lambda right.
That's my function and I'm assigning whatever it's returning, which is a lambda in this case to this
lambda right here called L five and now I'm calling it and when I call it it instantiate the lambda
executes that lambda that's being returned and you can see what displays this lambda was made using
make lambda.
We could pass parameters, we could do all kinds of things.
And again, it makes more sense to see this in the stateful context.
So I'll leave those examples for the next couple of videos.
But you can see it's pretty cool, right, that a lambda that's sorry that a function can return a lambda
and those lambda that we return can be pretty complicated as well.
Let's move over to Test six and there's just a couple left, couple of examples and this one's pretty
easy example to understand.
And we're over here in Test six.
So what do we do here?
Well, this is using auto in the Lambda Parameter list.
I mentioned this in the slides in the previous lecture.
Notice now I'm saying auto and auto.
So I'm telling the compiler, hey, compiler, you figure out what's going on.
This is pretty cool because we're not trying to create some generic template function here.
We're just doing it this way.
So again, l six is the variable.
Let the compiler figure out the type.
And what are we assigning to this variable?
Lambda no captur to parameters.
What are their types?
I don't know.
Let the compiler figure it out.
And within the body of that lambda, all we're doing is we're displaying.
And we're displaying why?
What's the type of X and Y?
Again, I don't know.
The compiler will figure it out.
So now that I've got my lambda my lambda expression in the variable L six, I can call it right here.
I'm calling it with two integers.
So the compiler sees this and says, oh that's it, that's in it.
Aha.
Intent 1020 is being displayed now.
I'm displaying it, I'm calling it with a double and an integer.
So it's displaying 100.3 and 200, right?
The double and the integer.
Here's two doubles.
That works too.
But this is where it's really neat.
I'm calling L six now and I'm passing in two person objects.
Larry 18, Curly 22.
These guys, the compiler is going to say, Oh, those are person objects.
Remember, I created that person class up at the top of this file.
So it's going to pass those things into this lambda.
Execute the lambda and it's going to display person Larry 18 person curly 22 Same thing we passed in
here.
Now, that's pretty cool.
Now, a couple of things that are happening here.
It's very important that whatever you pass in to this must overload this operator.
Right.
I mean, we're displaying these guys using this operator right here.
I've I have overloaded the insertion operator in that person class that I've already created up there.
So this is really important.
Otherwise you're going to get a compiler error that may not be too easy to read and it's going to say
something about operator less than less than not defined somehow.
It's not a problem here because the floats in the ints and the doubles all support the overloaded insertion
operator.
Last example.
This example right here is Test seven.
Also really straightforward example what we're doing here.
And let me scroll this up just a little so we can see it a little bit better.
I'm right here in Test seven.
What I've done is I've created a vector of person objects called stooges.
So there are Larry, Moe and Curly.
Larry's 18.
Moe is 30 Curl.
He's 25.
Now, what I'm doing is I'm calling some of the standard template library algorithm functions.
I'm going to use two of them.
I'm going to use stewed sort and stewed for each they take in lambda expressions, right, or function
objects.
In this case I'm using lambdas, so I'm calling Stuart sort and basically it says, well, what do you
want to sort?
Where does it start?
Where does it end?
So begin stooges and stooges.
Right, there's my vector.
I want to start at the beginning.
Go to the end.
Remember, this is just an alternate syntax for stooges.
Begin and end.
We could do it like begin like this or like this.
Either way it works.
And here is the lambda expression.
Remember stood sorte is expecting a function object.
So that's why I'm going to send it.
No capture list two parameters by Konst reference.
The first one is one person.
The other is the other person.
It's sorting.
So when you're sorting, you're comparing two things, right?
And moving them around.
Well, how does this guy know where to move things around?
Well, you need to tell it which one is bigger.
So in this case, I'm returning p one.
Get the name.
And if it's less than P two's name, I'm going to return.
True or false, depending on this condition.
Based on that condition, these two sort algorithm knows which one is greater, which one is less than,
and it can do what it's doing.
Now, this is pretty powerful.
This is, again, a predicate lambda right here.
You can see that this is a predicate lambda right here.
You're passing in some parameters and it's returning a boolean.
So that's exactly what's happening here and that's exactly what stood sort expects.
So what's going on?
I'm sorting the Stooges vector by name.
Now, when I finished this, this stood vector right here will be sorted.
Now I just want to display each element in there.
And to do that, I'm going to use another standard template library algorithm called for each.
Okay.
Now, what does this do?
Well, where do you want to start?
Where do you want to end?
And what do you want to do?
Right.
So it's going to loop through that vector.
That's what it's doing for each element in the vector.
It's going to loop through that vector.
And for each one of those elements, it's going to call this lambda function right here.
It's going to take that element in here.
Larry, Moe, Curly, pass it into here and I'm just going to display it.
So when I call this, look what happened right here.
Curly Larry Moe.
Notice it's sorted alphabetically.
Clem Right.
Curly Larry.
Moe It used to be Larry.
Moe Curly.
So this function right here that we called absolutely sorted that vector based on the condition in our
predicate lambda.
All right.
So one more example and we're right here now.
I'm calling stooge sort again.
This time I'm sorting based on age.
I want to sort based on age.
Same idea, right?
Give me the two parameters and return p ones age less than p two's age now stood sought knows which
one to put ahead of the other.
And once we do that, we're going to do this for each again in this code.
And this code are exactly the same.
But look what happens over here.
Now we're going to display Larry, Curly and Moe, but now they're sorted by age.
There you go.
This gives you a, I think, a pretty good introduction to different kinds of stateless lambdas using
references by value objects and so forth.
In the next video, we'll switch over and we'll start talking about stateful lambda expressions.
So I'll see you in that one.