Ch6.13: Lambdas
Overview
A lambda is a short way to write a small function directly inside your code. Lambdas are useful when you need a quick function for a one‑time purpose, such as a callback or a small calculation.
In this chapter, you will learn:
- how to write a lambda
- how to call a lambda
- how captures work
- how to use lambdas as callbacks
- how to write recursive lambdas
- why identical lambdas still generate separate code
1. Basic lambda syntax
The simplest lambda looks like this:
auto f = [] {
::fast_io::println("Hello from a lambda!");
};
f(); // call it like a normal function
The [] part is called the capture list.
2. Lambdas with parameters
Lambdas can take parameters just like normal functions.
auto add = [](int a, int b) {
return a + b;
};
::fast_io::println(add(3, 4)); // prints 7
3. Captures
Lambdas can use variables from the surrounding scope. To do this, you must list them in the capture list.
3.1 Capture by value
int x = 10;
auto f = [x] {
::fast_io::println(x);
};
f(); // prints 10
The lambda stores its own copy of x.
3.2 Capture by reference
int x = 10;
auto f = [&x] {
x += 1;
};
f();
::fast_io::println(x); // prints 11
The lambda modifies the original variable.
3.3 Capture everything
int a = 1;
int b = 2;
auto f = [=] { return a + b; }; // capture all used variables by value
auto g = [&] { a += b; }; // capture all used variables by reference
4. Lambdas and function pointers
A lambda with no captures can be used wherever a function pointer is expected.
int operate(int a, int b, int (*op)(int, int))
{
return op(a, b);
}
auto add = [](int a, int b) { return a + b; };
::fast_io::println(operate(3, 4, add)); // OK: no captures
A lambda with captures cannot be used as a function pointer.
int x = 10;
auto f = [x](int y) { return x + y; };
operate(3, 4, f); // ERROR: f has captures
5. Using lambdas inline
You do not need to store a lambda in a variable. You can use it immediately.
::fast_io::println(
[](int a, int b) { return a * b; }(3, 4)
); // prints 12
This is useful for quick one‑off operations.
6. Lambdas as callbacks
Lambdas are often used as callbacks. For example:
void repeat(int n, void (*f)())
{
for(int i{}; i != n; ++i)
f();
}
repeat(3, [] { ::fast_io::println("tick"); });
This prints tick three times.
7. Writing recursive lambdas
A lambda cannot refer to itself by name, because it has no name. If you want a recursive lambda, you must store it in a variable first and then call that variable inside the lambda.
Example: factorial
auto fact = [&](int n) {
if(n < 0)
::fast_io::fast_terminate();
if(n == 0)
return 1;
return n * fact(n - 1); // call the variable
};
::fast_io::println(fact(5)); // prints 120
The & capture is required so the lambda can call itself.
Example: countdown
auto countdown = [&](int n) {
if(n < 0)
return;
::fast_io::println(n);
countdown(n - 1);
};
countdown(5);
8. Identical-looking lambdas are still different
Even if two lambdas look exactly the same, the compiler treats each lambda expression as a separate function. For example:
auto f1 = [] { return 1; };
auto f2 = [] { return 1; };
auto f3 = [] { return 1; };
These three lambdas look identical, but they are three different functions. The compiler generates separate code for each one.
If you write many lambdas inside a frequently used function, this can increase the size of your program. To avoid unnecessary code growth:
- reuse the same lambda instead of creating many identical ones
- use a normal function when the logic is simple and repeated
- avoid lambdas inside hot loops unless necessary
Key takeaways
- A lambda is a short way to write a small function.
- Lambdas can take parameters and return values.
- Captures allow lambdas to use surrounding variables.
- Captureless lambdas can be used as function pointers.
- Recursive lambdas must capture themselves by reference.
- Identical-looking lambdas still generate separate code.
- Lambdas are ideal for callbacks and one‑off operations.