What is Lambda / Closure Function

A unnamed function that does not have a name, defined inside other function.

Why Closures Are Needed?
1. Variable is kept alive between function calls without using global variables. Global variables are risky because any part of your program can accidentally change them
2. (Only C++) If some logic/function need to be called again and again, then function is allocated on stack. This save stacks creation/deletion, jump instruction time

Syntax of Lambda


function_pointer  = [ ] () mutable throw -> return_type { 
    .....function body ......
};

[   ] called Capture List
    - captures local/Global variables defined outside lambda to be used inside lambda function.
    - Changing Values of passed variables:
    - Passed by value `[=]` are RO: These cannot be changed.
    - Passed as reference `[&]`: Can be changed.
() called Parameter list which is Optional
    - Function Parameters to be passed.
mutable keyword is Optional
throw keyword is Optional
return type is Optional.  //if return type is not specified its Deduced Automatically
        

Examples

Example Code
Pass by Value (RO)

Outside variable cannot be modified in lambda.
Passing 1 outside variable to lambda

int i = 1;
auto p =  [ i ]  (int a, int b)  ->  int {
    return a + b + i;
};
cout << p(2,3) << endl;            //6
                                
Passing all outside variables to lambda

int i = 1, j = 2;
auto p =  [ = ]  (int a, int b)  ->  int {
    //j=3;        //Error. assignment of read-only variable j
    return a + b + i + j;
};
cout << p(3,4) << endl;            //10
                                
Pass by Reference(&) RW
Passing 1 outside variable inside lambda

int i = 1;
auto p = [ &i ] (int a, int b)  ->  int {
    i = 5;  return a + b + i;
};
cout << p(2,3) << endl;            //10
                                
Passing all outside variables to lambda

int i = 1, j = 2;
auto p = [ & ] (int a, int b)  ->  int {
    return a + b + i + j;
};
cout << p(3,4);    //10
                                
Pass by ref and value in capture list
Capture by reference all except 1

// Except "j" everything else is captured as reference
auto p7  =  [ &, j ]  (int a, int b)  ->  int {
    i=7;
    return a + b + i;
};
                                
Capture by Value all except 1

// Except "i" nothing can be changed.
auto p8  =  [ =, &i ]  (int a, int b)  ->  int {  
    i=95;  return a + b + i; 
};
                                

return, break in lambda


int main() {
    string s = "abcdfg";
    for_each(s.begin(), s.end(), [&um, &out](const char ele){
        auto it = um.find(ele);
        if (it == um.end()) {
            out = ele;
            return;     //break cannot be used in lambda. This break will exit lambda not function
        } else {
            um[ele]--;
            if (um[ele] == 0)
                um.erase(it);
        }
    });
}
        

Generic Lambda (C++14)

auto can be used inside lambda. Earlier this use to give error.

auto ptr = [](auto x, auto y){ return x+y; };
string a = "Never", b = "GiveUp";

cout << ptr(1,2) << endl;                            //3
cout << ptr(a,b) << endl;                            //NeverGiveUp   
        

Lambda capture initializers


// Allows lambda captures initialized with arbitrary expressions.
auto f = [x = test(2)] { return x; };           //20  
        

Accessing class members inside lambda

Call by Value


class A {
    int  a = 3;
public:
    void f(){
        auto ptr = [*this] {    // this has to be captured to access members
            //a = 3;            // Error. Changing value of RO Object is not allowed
            cout << a;
        };
    }
};