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:

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:

Key takeaways