Lambda in C++

Introduction of Lambda expression in C++ and how to use it.

What is Lambda in C++

Lambda expression is a new feature since c++11. It is used to create anonymous function object to simplify programming process.

How Lambda expressions are composed

[capture](parameters) mutable -> return type {statement}

1
2
3
4
// ...
#include <functional>
// ...
std:function<int(int, int)> add = [](int a, int b) -> int {return a+b;};

capture

Capture variables from context.

capture statementmeaning
[]not capture any variable from context
[x, &y]capture x by passing value, y by passing reference
[&]capture all variables by passing reference
[=]capture all variables by passing value
[&,x]capture all variables by passing reference, expect x
[=,&x]capture all variables by passing value, expect x

parameter

Same as parameter in normal function. This part is optional actually when no parameter is needed. “()” parentheses can be omitted as well.

mutable / exception

It is a optional keyword. In default, lambda return a const range in another word you cannot change value captured from context. You can change it by adding mutable keyword.

exception is declare the exception type. like throw(int)

return type

Same as function return type. It is optional part. It can be omitted when return type is void or just one return keyword in statement so that compiler can automatically recognize.

statement

The function body where you can use variable captured from context and parameters. It can be empty but cannot be omitted.

How to use it

Functor

loop each element in a container (like map or reduce)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
std::vector<int> some_list;
int total = 0;
for (int i = 0; i < 5; ++i) some_list.push_back(i); // 0 1 2 3 4

std::for_each(begin(some_list), end(some_list), [](int& x)
{
    x++;
});
// some_list // 1 2 3 4 5

std::for_each(begin(some_list), end(some_list), [&total](int x)
{
    total += x;
});
// total 15

std::sort(begin(some_list), end(some_list), [](int a, int b){return a>b;});
// some_list // 5 4 3 2 1

Function

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#include <iostream>
#include <functional>
using namespace std;

int main(void)
{
    int x = 8, y = 9;
    auto add = [](int a, int b) { return a + b; };
    std::function<int(int, int)> Add = [=](int a, int b) { return a + b; };

    cout << "add: " << add(x, y) << endl;
    cout << "Add: " << Add(x, y) << endl;

    return 0;
}

Recursive

Same with function but you have to specify the type of function instead of auto. Because compiler cannot automatically detected the type recursive function when calling itself.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#include <iostream>
#include <functional>
using namespace std;

int main(void)
{
    std::function<int(int)> recursion = [&recursion](int n) {
        return n < 2 ? 1 : recursion(n - 1) + recursion(n - 2);
    };

    cout << "recursion(2):" << recursion(2) << endl;
    cout << "recursion(3):" << recursion(3) << endl;
    cout << "recursion(4):" << recursion(4) << endl;

    return 0;
}

Meanwhile, tail recursion:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <functional>
using namespace std;

int main(void)
{
    function<uint64_t(uint64_t, uint64_t, uint64_t,uint64_t)> fibo = [&fibo](uint64_t a, uint64_t b, uint64_t cur, uint64_t r){
    	if(cur != r)
	    	return fibo(b, a+b , cur+1, r );
  		return b;
    };

	function<uint64_t(uint64_t)> recursion = [&fibo](uint64_t n) {
		if (n < 2)
            return (uint64_t)1;
		return fibo(1, 1, 1, n);
	};

	uint64_t in = 35;
    cout << "recursion("<< in <<"):" << recursion(in) << endl;
    return 0;
}