WEBVTT

00:00.210 --> 00:06.000
Hello again! In this video, we are going to have an introduction to lambda expressions. When we call

00:06.000 --> 00:12.270
an algorithm function, like find_if(), we have been using functors, or sometimes function pointers.

00:13.020 --> 00:19.650
So we pass an object of a functor class or a function pointer as the callable object, and that will

00:19.650 --> 00:23.640
customize the way the find_if() call actually processes the elements.

00:24.360 --> 00:27.180
In this case, we have a class, is_odd.

00:28.620 --> 00:34.170
It has an overloaded function call operator, which takes an int. And it will return

00:34.170 --> 00:36.200
true if that int argument is odd.

00:38.340 --> 00:43.650
So if you imagine you were writing this code. You write your main() functions, you declare your vector.

00:44.370 --> 00:50.000
Then you start writing your find_if() call, begin(), end() - ah! I need a callable object.

00:50.610 --> 00:53.730
So you have to scroll up before the start of the current function.

00:54.360 --> 00:55.590
Find a bit of empty space.

00:56.310 --> 01:03.210
Think of a unique name for your class or function, and then write the code. And then you come back here.

01:03.210 --> 01:04.890
And then, "what was I doing?"

01:05.100 --> 01:05.660
Oh yes, find_if().

01:06.630 --> 01:08.550
So it is all an unnecessary interruption.

01:08.790 --> 01:11.130
And also, all this code does take up space.

01:12.210 --> 01:17.400
What if we could actually watch the code inside the algorithm call? So we could just put the

01:17.610 --> 01:19.770
return n mod two equals one in here?

01:20.460 --> 01:23.310
Would that not be better? In modern C++,

01:23.310 --> 01:26.010
we have lambda expressions, which allow us to do this.

01:26.760 --> 01:29.550
These are, if you like, anonymous local functions.

01:30.150 --> 01:36.570
Other languages have similar things, sometimes called closures. And no doubt, debates about whose implementation

01:36.570 --> 01:38.280
is the best or the most accurate!

01:40.340 --> 01:45.680
When the compiler encounters one of these lambda expressions, it will generate some code, which defines

01:45.680 --> 01:46.730
a functor class.

01:47.510 --> 01:53.030
So this class will have a name, which is chosen by the compiler. And it is guaranteed to be unique, and

01:53.030 --> 01:54.920
not to conflict with anything else in scope.

01:56.420 --> 01:58.580
This class will have a function call operator.

01:59.000 --> 02:04.850
The body of this will be the same as the code in the lambda expression. And the return type of this

02:04.850 --> 02:08.420
function call operator will be the same as the lambda expression.

02:08.870 --> 02:12.590
And usually, the compiler will be able to work out what the return type is.

02:13.910 --> 02:19.730
And then the compiler will add code, which will create an object of this class, at the point where the

02:19.730 --> 02:21.410
lambda expression appears in the code.

02:23.170 --> 02:28.060
Lambda expressions are anonymous, and they're defined in lines. So we just write the code where the lambda

02:28.060 --> 02:28.690
expression is.

02:29.440 --> 02:33.340
We start off by putting a pair of square brackets, where the function name would go.

02:33.700 --> 02:36.040
That indicates that we are starting a lambda expression.

02:36.880 --> 02:41.710
Then we have a pair of round brackets which contain the function arguments. Just like they do for a normal

02:41.710 --> 02:42.160
function.

02:42.640 --> 02:48.370
So there we are, we have square brackets and the arguments. And then we have a pair of curly braces which contain

02:48.370 --> 02:50.710
the actual code that we want to be executed.

02:51.850 --> 02:53.920
So that is just like writing an inline function.

02:57.060 --> 03:02.820
If we find this as a single statement, which returns a value, the compiler will be able to deduce

03:02.820 --> 03:06.900
the return type, in all versions of C++, which support lambda expressions.

03:07.470 --> 03:12.420
So in this case, the compiler can see that this will return a bool. And the return type from the function

03:12.420 --> 03:17.640
call operator in the class that it generates will be bool. So the compiler will generate the

03:17.640 --> 03:19.440
code for this functor class.

03:19.830 --> 03:22.860
And it will also add some code which will create an object of this class.

03:23.400 --> 03:29.280
And the functor class that the compiler generates will be exactly equivalent to the class that we

03:29.280 --> 03:30.180
had in our example.

03:31.530 --> 03:33.840
So the algorithm call would look like this.

03:33.840 --> 03:39.300
We have the iterator range again, and then, for the callable object, we write a lambda expression.

03:39.720 --> 03:44.010
So that is the pair of square brackets, the argument and then the inline code.

03:45.120 --> 03:47.460
So here is the code again with a lambda expression.

03:47.730 --> 03:49.260
And you will notice it is much shorter.

03:50.790 --> 03:52.380
So we have the vector of ints again.

03:52.590 --> 03:56.100
Then we have the find_if() call, and there is the lambda expression.

03:57.520 --> 03:58.840
So let's see if this works.

04:01.380 --> 04:03.260
Yep, first odd element is 3.

04:03.740 --> 04:05.180
So this is much easier to write.

04:05.210 --> 04:11.210
You can start off declaring the vector. Then you write your find_if(), begin(), end(). "What do I want this

04:11.210 --> 04:13.850
to do? Oh yes, if n mod two is equal to one..."

04:14.150 --> 04:16.490
And then you can carry on, without having to interrupt yourself.

04:17.360 --> 04:20.300
And if you are reading the code as well, this is much easier to follow.

04:20.660 --> 04:23.990
The code is actually where it is used, as opposed to somewhere else.

04:24.560 --> 04:30.910
As C++ has developed and we have more experience with lambda expressions, compilers are getting better

04:30.920 --> 04:36.380
at deducing return types. In C++ 11, the first version with lambda expressions,

04:36.890 --> 04:42.200
the compiler can only deduce the return type if the expression is a single statement, which returns

04:42.200 --> 04:44.120
a value. For anything else,

04:44.240 --> 04:48.290
even if you have multiple statements which return a value, the compiler will put void.

04:48.950 --> 04:54.590
If you want a return type, then you have to put it yourself, with this arrow followed by the return

04:54.590 --> 04:54.920
type.

04:57.860 --> 05:03.890
In C++14, the compiler can deduce the return type, provided it is the same in all branches.

05:04.520 --> 05:10.620
So if we put an if statement in here, then the if clause and the else clause would both have to return

05:10.620 --> 05:15.420
a bool. In C++17, that is no longer required.

05:15.470 --> 05:19.550
So you can have one branch which returns int, and another one which returns string, and so on.

05:19.970 --> 05:22.610
And the compiler will deduce the return type?

05:23.990 --> 05:25.670
Okay, so that is it for this video.

05:26.030 --> 05:26.890
I will see you next time.

05:27.170 --> 05:29.090
Until then, keep coding!
