Chapter Function Pointer berakhir dengan catatan: membuat fungsi bernama hanya untuk satu pemanggilan callback terasa berat — nama itu dideklarasikan jauh dari tempat pemakaiannya, padahal logikanya kecil dan tidak dipakai di mana pun lagi. C++ modern menjawabnya dengan lambda expression: fungsi tanpa nama yang ditulis langsung di titik pemakaiannya. Lambda adalah salah satu fitur yang paling mengubah gaya menulis C++ sejak C++11 — ia membuat kode jadi lebih ringkas karena logika dan konteksnya berdampingan. Pada Chapter ini kita membedah anatomi lambda, menyimpannya di variabel, memanggilnya langsung, dan mencicipi penggunaannya bersama std::for_each.

Anatomi Sebuah Lambda #

Bentuk paling umumnya: [captures](parameters) { body }. Kurung siku pembuka adalah tanda lambda — dan sekaligus daftar capture, variabel luar yang diserahkan ke dalamnya (topik utuh Chapter berikutnya). Bagian parameter dan body mengikuti kaidah fungsi yang sudah kita kuasai. Program berikut memakai lambda dalam tiga wujud:

cpp
#include <iostream>
#include <string>

int main() {
    // Lambda disimpan di variabel auto, lalu dipanggil seperti fungsi
    auto sapa = [](const std::string& nama) {
        std::cout << "Halo, " << nama << "!\n";
    };
    sapa("Budi");

    // Lambda dengan return value
    auto jumlahkan = [](int a, int b) {
        return a + b;
    };
    std::cout << "7 + 8 = " << jumlahkan(7, 8) << "\n";

    // Anonymous function: didefinisikan dan dipanggil langsung (IIFE)
    std::cout << "10 * 10 = "
              << [](int x) { return x * x; }(10) << "\n";
    return 0;
}

Output yang Dihasilkan:

text
Halo, Budi!
7 + 8 = 15
10 * 10 = 100

Mari kita bedah ketiga wujudnya. Baris 7 (auto sapa = [](const std::string& nama) {...};): lambda disimpan ke variabel auto — kata kunci auto yang kita pelajari pada Chapter auto dan Type Deduction diperlukan karena lambda punya tipe khusus yang tidak memiliki nama yang bisa kita tulis; setelah tersimpan, sapa("Budi") dipanggil persis seperti fungsi. Baris 13-15: lambda jumlahkan mengembalikan nilai; return type-nya tidak ditulis dan compiler menyimpulkannya dari return a + b — yaitu int. Baris 19-20: pola IIFE (immediately invoked function expression) — lambda ditulis, lalu langsung dipanggil dengan (10) di ujungnya, tanpa pernah disimpan; pola ini berguna untuk membungkus blok logika sekaligus menghitung hasilnya di tempat. Parameter lambda mengikuti semua aturan passing yang kita pelajari — perhatikan const std::string& di sapa, kombinasi hemat-aman dari Chapter Pass by Const-Reference.

Lambda bersama std::for_each #

Panggung utama lambda adalah standard library: algoritma seperti std::for_each menerima “apa yang harus dilakukan” sebagai parameternya, dan lambda adalah cara paling ringkas menyusunnya. std::for_each sendiri baru akan kita bahas tuntas pada Section Iterators dan Algorithms; untuk sekarang cukup tahu ia menjalankan sebuah fungsi untuk setiap elemen container, dan .begin()/.end() adalah penunjuk posisi awal dan akhir elemen:

cpp
#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> stok = {3, 5, 7, 9};

    // for_each menjalankan lambda untuk setiap elemen vector
    std::for_each(stok.begin(), stok.end(), [](int nilai) {
        std::cout << nilai * 2 << "\n";
    });
    return 0;
}

Output yang Dihasilkan:

text
6
10
14
18

Lambda [](int nilai) { std::cout << nilai * 2 << "\n"; } dikirim sebagai argumen ketiga, dan std::for_each memanggilnya sekali per elemen {3, 5, 7, 9}. Bandingkan dengan alternatif tanpa lambda: kita harus mendefinisikan void cetakGandakan(int nilai) di luar main() — lengkap dengan nama, tipe, dan jarak dari pemakaiannya — untuk tugas yang jelas-jelas hanya hidup di satu baris ini. Lambda menyatukan keduanya: logika kecil tinggal tepat di tempat ia dipakai.

Kapan Lambda, Kapan Fungsi Bernama #

Lambda bukan pengganti fungsi bernama, melainkan pelengkap untuk wilayah tertentu. Sebagai pedoman memilih:

  • Lambda: logika kecil, sekali pakai, maknanya bergantung pada konteks di sekitarnya — callback algoritma, pembersih sumber daya, pembanding sementara.
  • Fungsi bernama: logika yang dipakai lebih dari satu tempat, butuh pengujian sendiri, atau cukup besar untuk layak diberi nama dan dokumentasi.

Satu kemampuan besar lambda belum kita sentuh: membaca dan mengubah variabel di sekitarnya lewat daftar capture di dalam kurung siku. Daftar kosong [] pada semua contoh di atas artinya lambda berjalan mandiri tanpa menyentuh dunia luar — padahal justru di situlah kekuatan sebenarnya. Rujukan resmi: cppreference: lambda expressions dan cppreference: for_each .