Hello again! In this video, we are going to look at lambda expressions and partial evaluation. The main
use for lambda expressions is for writing in-place
local functions, in things like algorithm calls. Lambda expressions are first-class objects.
In fact, a lambda expression is an object.
It is an object of the functor class that the compiler generates.
We can store a limited expression in a variable. So we can write a lambda expression, and then the compiler
will create an object.
We cannot know the type of this object because it is a class that is defined by the compiler.
So we have to use auto, and the compiler will provide the name for us. And then we can pass this as a
callable object, to something like an algorithm call.
So that is the same code we had before, but we are splitting the lambda expression and the algorithm
call into two separate statements.
So here is that code.
So this is the same code as before, but with the lambda expression split out.
And we get the same result. Because a lambda expression is a first-class object, we can also return it from
a function, as well as passing it to a function. So we can write a function which returns a lambda expression.
Again, we have to use auto for the return type, which is allowed in C++14.
Then we have a lambda expression in the function body, which is just returned.
So this lambda expression will capture the function argument, because that is a variable which is in
scope, in the function body.
And then you can do something inside the body of the lambda. The lambda
will also take an argument itself.
So this lambda is going to capture this "salutation" argument, and then it will append some of the things to
it, including its arguments.
So if we call this function, "greeter", with the argument, "Hello", then the lambda expression will capture
this argument,
"Hello".
So this "salutation" will now have the value
"Hello".
And then, when we call the lambda expression with an argument, it will append a comma and the argument
to the string,
"Hello".
So this "greet" that is returned is a lambda expression.
It takes someone's name as argument, and it adds a greeting to it.
So let's look at this code again.
There is the lambda expression. There is the function that returns the lambda expression. We call the function
with the argument, "Hello", so salutation in this lambda is now "Hello". And then we store the returned
lambda expression.
So when we call this lambda expression with the argument "students", the argument here is going to be
"students", the salutation is going to be "Hello".
So the lambda is going to return,
"Hello, students".
And similarly, when we have "greet" with argument "James", the argument will be James, the salutation
will be hello.
So this will say "Hello, James".
Partial evaluation is a functional programming technique, in which data is evaluated in stages. As an example,
if you open a large document
The obvious approach is for the document viewer to format the entire document before you can start
reading it.
If you have a 700 page document and you only want to look at the first two pages, that could be
quite a long time.
A better solution is to format each page as the user looks at it.
So when you open the document, it will format page one.
Then when you go to page two, it will the format page two and display it.
And that will be much quicker.
And if you jump to Page 537, it will just process Page 537 and ignore all the intervening pages.
Another example is if you get data in stages and you can process each bit of data independently.
So if you get some data, and you wait, and you get some data, and you wait, and you get some more data and
you wait. And then you process it all at the end. So all that waiting time was wasted.
Alternatively, you could get some data. Process it. Then get some more data, then attach it to what
you have already processed. Then get some more data, process that, and so on.
Obviously, this will not work for every problem.
But if you can do it, it will speed things up, quite a lot.
So, partial evaluation reduces computation, and it can make processing simpler. And there are lots of
applications where it is used: artificial intelligence, database query engines, scientific computing and
so on. And we can implement partial evaluation by using lambda expressions.
In fact, we have already done that.
With this lambda expression, we have a function which has processed the salutation,
"Hello".
And then it just processes the name of the person as it gets it.
So "greeter" performs a partial evaluation.
So the important point is that it only needs to process the salutation once.
And then, once it has done that, the code which processes the person's name does not need to know what
the salutation is, or how it is processed, or where to get it.
If we want a different salutation, then we call "greet" again with a different argument.
So this time we are going to say "Good morning" and then the person's name.
So here is the code again, with our function returning lamba. And we are greeting with "hello".
Then we can call this again with a different argument.
So that is now going to bind
"Good morning" to the salutation.
So if we call this "greet_formal" with someone's name, it is going to say "Good morning" and then the person's
name.
So there we are.
"Good morning,
Dr Stroustrup"
And finally, one thing you need to be careful about when you are using stored lambda expressions, if
they capture by reference. You probably know that returning a reference to a local variable
is dangerous.
If we have something like this, so we return a variable which is local by reference. That variable
will be destroyed when the function returns.
And then you have a reference which is referring to nothing.
So that will probably crash the program if you try to use it.
When we have a lambda which captures by reference, that will have a reference to the captured variable.
If we call this lambda after the captured varaible has gone out of scope,
then we have the same dangling reference problem.
So if you are using capture by reference, make sure that the captured variable is still valid when you
call the lambda.
Okay, so that is it for this video.
I'll see you next time, but meanwhile, keep coding!