Lambda¶
Motivation¶
|
Reverse sorting … static bool greater(int lhs, int rhs)
{
return lhs > rhs;
}
// 2 kilometers down below ...
std::sort(v.begin(), v.end(), greater);
|
Lambda To The Rescue¶
“Lamda” (Python, Perl, …)
Definition is usage
Reverse sorting: lambda version …
std::sort(v.begin(), v.end(), [](int lhs, int rhs) { return lhs>rhs; });
Excursion: Python Closures¶
Python’s closures are all automatic
Created at function definition time
⟶ runtime
Closure = snapshot of names that are …
Undefined in local scope of defined function (
print_message
)Defined in surrounding scope (parameter
message
of creating functioncreate_print_function
)
def create_print_function(message):
def print_message():
print(message) # <--- message is 'in the closure of function object "print_message"'
return print_message
p = create_print_function('howdy')
p()
$ python ../code/closure.py
howdy
Same In C++: Capturing¶
#include <functional>
#include <string>
#include <iostream>
static std::function<void()> create_print_function(const std::string& message)
{
auto print_message = [message](){ // <--- message is 'captured into the closure of function object "print_message"'
std::cout << message << std::endl;
};
return print_message;
}
int main()
{
auto p = create_print_function("howdy");
p();
return 0;
}
$ code/c++11-lambda-capture
howdy
Here: explicit capture
Variable
message
is captured into lambda function objectCapture is by copy if not stated otherwise (see below)
So What Is That? (Answer: A Functor)¶
Functor: an instance of a class that happens to be callable (has
operator()(...)
defined)Nothing more
Note
Go through Live Hacking: Handwritten Functors (Too Much Boilerplate)
Capturing By Reference ⟶ Careful!¶
#include <functional>
#include <string>
#include <iostream>
static std::function<void()> create_print_function(const std::string& message)
{
auto print_message = [&message](){ // <--- message is 'captured into the closure of function object "print_message"'
std::cout << message << std::endl;
};
return print_message;
}
int main()
{
auto p = create_print_function("howdy");
p();
return 0;
}
$ code/c++11-lambda-capture-reference
howdy
Program creates a temporary
std::string
object ("howdy"
)Lambda stores a reference to it, and uses it later
⟶ Attentive programmer jumps up and shouts!
Danger
Be very careful!
Use capture-by-reference only when references are use locally (for example, passing to algorithms)
Don’t use capture-by-reference in lambdas that you store on the heap, for example, or that you pass to other threads