Now that we've seen how to implement both stateless and stateful lambdas, let's take a look at more
ways to use them.
The most predominant use of lambdas is in conjunction with the standard template algorithms library
as either a predicate or operator.
Remember, a predicate is just a function that takes several arguments and returns a boolean.
Alternatively, an operator is a function that takes several arguments and applies some operation to
them.
When using lambdas with the SQL Algorithms Library, you'll often hear them referred to as either urinary
binary predicates or urinary binary operations.
This simply refers to whether the lambda will act as a predicate or as an operator, and how many parameters
the lambda requires.
Urinary meaning one in binary meaning to.
We've already seen lots of examples that use lambdas with the SQL algorithms.
We've seen examples in this section and we also saw examples in the SQL section of the course.
Now that we've got the jargon down, let's take a look at a few more examples of how to use lambdas
with a few more SQL algorithms.
Okay.
So then let's go through some examples in the ID.
You can see here that I'm in the Section 21 workspace and I'm in the SQL Underscore Lambdas Project.
I've already gone ahead and built and run it.
You can see the run out here on the right side and let's go over the includes I o stream vector algorithm
and I'm also including numeric.
This is for a function called iota, which is pretty handy little function that I haven't covered.
So I thought I would throw it in just so you could learn it.
The algorithms that I'm going to be using in here are pretty straightforward ones.
There are a lot more of them.
As I said, please see your CPP reference website.
It's got documentation on all the SQL algorithms.
Again, this video is not about the algorithms, it's about using lambdas with them.
Let's go over some examples.
I've got, I think seven tests that will run and I'll walk through them just like I have before the
first one we've already seen before.
It's for each and I've included this as well as sort in this video.
In case somebody jumps straight into this video and they haven't seen them before, they can see them
here for the first time and I'll walk through them again.
Okay, so let's start with test one.
You can see test one's output is right up here in test one.
What we've got is we're going over the for each algorithm.
Now I've already covered the for each algorithm a couple of times in this section as well as in the
course.
It's a very handy algorithm that lets you iterate over a container in the standard template library.
So it's not modifying.
So we're not going to modify anything in the container.
It just basically processes each element, if you will.
In this case, I've got nums, which is a vector of five integers, and I've initialized it to ten,
20, 30, 40, 50.
And then what we're going to do is we're going to call for each from the beginning to the end.
So we're going to cover the entire container.
We don't have to we can only loop once or twice or three or four elements, whatever we want.
But in this case, I'm iterating over the entire vector.
And what's going to happen is for each element in that vector, it will be passed into this lambda and
we're not doing that right.
The for each algorithm is doing that.
And then we just use this lambda as an operator here, not a predicate, it's just a regular operator.
We just do some stuff.
So in this case we're just displaying.
So it's going to iterate past those guys in notice.
There's no capture.
We only have that one parameter which we need because for each is giving it to us and it's just going
to display ten, 20, 30, 40, 50.
So this is a really, really simple example of using a lambda with one of the algorithms in the standard
template library, a very handy algorithm as well.
I'm using, it's here, but this can be a container of anything.
OC So let's take a look at a different one that we probably haven't seen before.
This one is called is permutation, this one is called is permutation and it's also non modifying.
In this case I'm using triangles, so it tests whether two triangles are equivalent and we defining
a triangle being equivalent as a triangle is a vector of three points in any order.
So regardless of the order, if two triangles contain those same three points, they're equivalent.
So pretty simple definition.
So before we use the algorithm, let's take a look at what we've done.
Let me scroll up just a little bit here.
So here's test two and you can see test choose output right over here.
And I've got a structure that I've defined called Point, which is just an X Y attribute.
And then I'm going to create four points .1. to .3.4.
And based on this points, I'm going to create a triangle.
So a triangle is a vector of points, three points triangle one is 0.1.2.3 triangle two is 0.2.3.1.
And then triangle four includes that 0.4 here.
So according to our definition, these two are equivalent because we can change the order, right?
I think everybody understands what a permutation is.
We're just kind of mixing these things up in different orders.
Eventually we can commute one of these and get one of those because we've got one, two, three in both
of them.
However, triangle three is not equivalent because that 0.4 doesn't exist in either triangle one or
triangle two.
And again, the important thing is the lambda here.
So I'm going to call stood is permutation.
I'm going to pass in triangle one, begin triangle one, and that's going from the beginning to the
end of this vector.
And then I'm passing in triangle to begin.
Let me spread this out just a little so you can see it.
So we are also expecting two points now the stood is permutation function.
That's what it's doing.
It's passing those two points into us and it's up to us to compare them however we like.
So we're getting the left hand side and the right hand side and it's using the operator equal to compare.
So what's going to happen is I'm going to compare my left hand sides X to my right hand side sex and
the left hand sides Y to the right hand side y.
So our points are equivalent.
So when we call is permutation and we get a permutation that matches one of those, we've got an equivalence
and that's pretty much it.
So we're using that in the if statement and if they're equivalent, we're just displaying that.
If they're not equivalent, we're displaying that.
And you can see from this test case right here, that triangle one and triangle two are equivalent.
And that's exactly what's being displayed right over here.
Let me move this back because I think everybody sees what's going on now.
In the other example down here, I'm using triangle one and triangle three.
Now, remember, a triangle three has that fourth point in there.
So it's not going to be equivalent.
And that's exactly what happens right here.
We've got triangle one.
Triangle three is not equivalent.
So again, just another example of passing in a lambda here.
This lambda does not capture and it expects two parameters in this case.
This is a predicate, lambda, because it's returning a true false value.
All right.
So let's move on to test three.
In test three, I'm using the transform algorithm.
This is a modifying operation.
And if you recall in the previous examples, we created that Lambda Bonus where we awarded bonus points
to test scores and so forth.
Well, we're going to do the same thing, except we're going to use to transform.
So let's do it.
We've got test scores and it is a vector of integers and those are my test scores 93, 88, 75, 68,
65.
And these are the bonus points that I want to add to each one of those test scores right away.
You know, we've got a local variable here.
If we're going to use that in the lambda, we need to capture it.
So that's what we're going to do in this example.
We are going to transform that container.
Test scores begin, test scores don't end.
So we're doing the entire container and we're going to start writing back the information at test scores
again.
So we're going to start from here and we're going to start updating from here as well.
We're capturing bonus points by value.
That's this guy right here.
So we're going to capture those bonus points by value.
And then it stood transform is going to pass into the lambda each one of those scores as it iterates
over it.
So those scores will be passed into here 93, then 88 and 75 and so forth.
So what we're doing now is we're returning score plus equals five in this case.
So what we're going to do is we're going to increment each one of those test scores by five points.
So let's take a look at the output right over here.
Right here.
You can see I'm in test three and you can see right there that we've gone from 93 to 98, from 88 to
93 and so forth.
So we've added five points to each one of those scores.
I just used a range based for loop here.
I could have used the for each algorithm as well.
I'll leave that up to you guys to decide.
Okay, so let's take a look at test four.
I've got a vector of integers called nums and you can see I've initialized it here to one, two, three,
four, five.
Now what we're going to do is we're going to remove the even numbers from that vector.
Then once we remove them, we're going to erase them.
So what we're doing here is first we're calling remove if and we're telling remove if that we want to
iterate over the entire container numbers from beginning to end.
And what remove if we'll do is it will pass in each one of those values from that container into this
lambda.
This is a predicate lambda and we're returning true for whatever we want to delete.
So in this case we're returning true for all even numbers.
So two and four are what we want to eventually erase, which right now we're just removing.
What happens is it puts those numbers at the end and sets the end to it.
So now we're telling nums dot erase to erase what it returned and use nums end as the new end.
So it's basically going to chop off those numbers.
And then when we display our updated numbers, you can see right there, one, three and five.
So again, another example of using a predicate, lambda.
This is using the erase remove idiom, which is a very common idiom in the SQL.
Okay.
So let's move on to test five and test five.
I'm using that same person class that I've used throughout this section.
So it's right here.
You can see it's that person class with our overloaded insertion operator.
We've got our name, our age and a bunch of constructors and getters and setters.
So you can refer to the previous videos where I explained this in a little bit more detail.
So what we're going to do now is we're going to sort it now.
You seen this before in the previous video.
I just wanted to include it again, just to be complete because somebody may jump into this video and
not have any idea how it works.
So now, you know, so in this case, really easy.
I've created three person objects, person one, person two in person three, you can see them right
here.
They're emo and curly.
Then I've created a person vector and I've just created it using person one, two and three.
I've initialized it to those person objects.
This is just another way to do it.
I believe I've done it in the other videos, just using Move.
And then we're going to cost sort and we're going to tell students sort that we want to sort that people
vector from begin to end.
And I want it to pass me pairs of persons where that I need to compare.
So it's going to send to me two person objects, one on the left, one on the right, and we're using
the less than operator to compare those two, and we're going to compare by name.
So in this case, you can see we're just comparing by name and we're sorting in increasing alphabetical
order and then we're displaying these.
So what's going to happen is right here, Curly Larry and Moe CLM, right?
So it's in alphabetical order.
So in this case, if we wanted to display the people in that vector by age and in descending order,
then we would just have to say left hand side get age greater than right hand side get h and it will
display.
Moe, Curly and Larry in that order 30, 25, 18 and descending age, really powerful stuff.
All we're doing is changing that lambda, changing that predicate lambda to do what we need.
It's our functional requirements.
If we have to sort by name ascending or by descending, it's really, really easy to do.
All right.
So let's let's move on to another one that's a little bit different.
In this case, I've written a function and that function is called in between.
That function expects a vector of numbers, integers in this case, and I'm passing that in by const
ref a start value.
In an end value, it's going to decide whether all the numbers in that vector are between that start
value and that end value inclusive.
One to use the stood all of algorithm.
It's a non modifying algorithm and what it does is it tests whether all the elements contained within
the sequence satisfy the condition in the lambda.
So in this case I'm assuming that they don't.
So I'm just initializing this result boolean to false.
And then I'm saying result equals stood all of where do I want to start?
I want to start at nums dot begin and I want to go all the way to nums dot n so again, the entire container
I need start value and end value.
So I need to capture those guys.
And that's what's happening right here in the capture list.
I need to know what they are to be able to use them in my lambda right in here.
And withstood all of is going to do is for each element in that container.
It's going to pass it into this lambda.
And all I'm going to do is I'm going to say return.
The value is between star value and end value.
That's what that logic is saying right here.
I'm going to return result.
So really straightforward, really powerful, too.
We don't have to deal with any of this ourselves.
We just here is test six.
Let me scroll this up a little bit as well so you can see the test six output right up here and here's
test six.
I'm setting student alpha just so I can display true false rather than zero one.
So I'm starting with a vector of ten integers called num.
I'm using perrins here, not curlies, so I'm not initializing the first element of that vector to ten.
I'm creating a vector of ten elements and then I'm using that iota function which is in the numeric
library.
And what it does, it goes from nums dot begin to num start end and I'm providing one.
So basically what it's going to do is it's going to set the values in those ten integers to one, two,
three, four, five all the way to ten.
If I'd have started this at ten and here it would go from ten, 11 to 12 and so forth.
Really handy way assigned values to an existing container in incrementing order.
So I'm displaying that and you can see right there that's exactly what I owed has done one through ten,
so I'm going to call in between.
That's my function that I wrote up here.
I'm going to pass in the vector, I'm going to pass in the start in the end.
And what it's going to do is going to check to see if every element in that container is between 50
and 60.
Well, that's not true, right?
Because the container contains one through ten, so they're not all between 50 and 60.
In fact, none of them are between 50 and 60.
So that's going to return false in this case.
I'm going to check to see if the numbers are between one and ten.
Well, they are each returning.
True.
And in this case, I want to check to see if the numbers are between five and seven.
Of course they're not.
So that returns false as well.
Okay.
So then finally, we're at the last test here, test seven.
And this was a little bit more complicated, but it's pretty cool.
We have a class called Password Validator and it contains an attribute called Restricted Symbol.
And in this case, this is a single character that's the dollar sign.
So basically passwords cannot have dollar signs in them.
Then I've got a method called is valid, so we're going to pass in a password and this method is going
to tell us whether it's a valid well, it is valid if it doesn't contain that one symbol in this example.
So what this is going to do, it's going to check all of the characters in the password and be sure
that none of them are the dollar sign right now.
We could write loops and we could do all kinds of stuff to do this ourselves, but why not use the algorithm?
All of so let's do that.
I'm checking password from begin to end.
Password is a string, so it's basically a container of characters.
And again, I'm using all of I need to capture this object because I need access to that guy right there.
Restricted symbol.
So remember, we're capturing the object here.
The pointer all of will pass in each character of the password into this lambda.
So now we have everything we need and this will return character not equal to restricted symbol.
So this if the character is not equal to the restricted symbol, we've got a valid password.
And that has to happen for all of the characters.
If any of those fail, it's going to return.
False.
Pretty cool.
So let's see how we would use it.
I've got another example down here that I'll go over in a second, but let's take a look at the all
of and how we would use it right there.
So we've got a password we're creating called Hollywood one with a dollar sign again.
So this is an invalid password because of that guy.
Now I'm instantiating my password validator and I'm just simply calling.
PV one is valid and I'm passing the password into it.
That's it.
Simple as that.
It's going to return.
True if the password is valid.
False if it's invalid.
Well, in this case, we know that that password is not valid because it has the dollar sign in it.
If we change the password to just Hollywood one and execute this code, it will display is valid.
Okay.
So hopefully that makes sense.
You can see what's happening.
It's pretty easy.
We've got characters coming in from that password string and we're comparing them to that restricted
symbol we need to capture.
We need to capture the at this point or otherwise, we won't have access to restricted symbol.
Let's take a look at another example.
This is very, very similar.
This is password validator, too.
The big difference here is I don't have a single character of restricted symbols.
I've got a vector of restricted symbols.
So in this case, I've got a vector of characters.
The bang, the dollar and the plus symbol are all restricted.
That would make it an invalid password.
It changes our logic a little bit, but you can see the power here.
I've still got my is valid method that expects that password.
But what's going to happen now is I'm going to use all of and none of together.
Now that's pretty cool.
So let me show you how that works.
So you could walk through this really carefully, but basically what it's doing, it's making sure that
all of the characters in the password are not restricted.
And in order to do that, we're using stood all of and stood none of.
So again, what we're doing is we're making sure that all of the characters in the password have none
of the restricted symbols in them.
And if we run this example, we've got C++ rocks that has a bunch of illegal characters in it, right?
It's got the plus and the bang.
So we're initializing PV two and we're checking whether it's valid password or not.
Well, it's not valid because it's got the pluses and the bang.
In this case, we've got a single bang.
That's also not valid.
And then in this case, we have none of those characters.
Therefore, the password is valid.
In this video, we've seen some common SQL algorithms and how to use lambdas with them, but it's important
to note that this in no way covers them all.
There are many, many algorithms in the SQL Algorithms Library that use lambdas, and as we saw with
the class password validator too, they can even be used in conjunction with one another.
It would be impossible to cover them all, but hopefully this gives you a good understanding of why
lambdas are so important and their patterns of use.
Learn the SQL algorithms.
They'll become your best friends.
Also, if you're a competitive programmer, consider using the SQL algorithms before you code your own
solution.
Okay.
So that wraps up this section on Lambdas.
I hope you find this section useful.