Lambda's are inline anonymous functions/ functor's introduced in C++11. They are extensively used for higher order programming which helps in keeping the code DRY (Don't Repeat Yourself) by abstraction. Ex, Abstracting the collection iteration mechanics etc
Lambda's and closure's that had been supported by many dynamic programming languages for higher order/ functional programming are now supported by C++ with C++11. It helps in passing and returning functions like data.
let us consider abstracting collection iteration mechanics. STL provides many types of containers for storing a collection of data with iterators to access the data. The iterator's are used to iterate over all the elements in the container to perform operations on every element.
Example:
Defining functions that take lambda's as parameters:
In the above example, what could be the prototype of
1. The lambda's type can be prototyped with generic templating.
2. The lambda's without capture variables can be cast into function pointers.
3. The lambda's type can be automatically deduced in C++11 with
4. The lambda's type can be defined with
The lambda can not only be used as a functor object which can be passed to other functions. Closure's can be constructed i.e, the functions can access the variable's in the enclosing scope.
Simplified Syntax:
A simple example:
The function func takes a lambda parameter which captures the variable
It should be noted that the advantages gained with lambda's can be achieved with function objects too. Thus, lambda's are syntactic sugar which eliminate the need to write function objects elsewhere in the code which is expected to be used only once, keeping the code DRY and in writing elegant functional programs.
Lambda's and closure's that had been supported by many dynamic programming languages for higher order/ functional programming are now supported by C++ with C++11. It helps in passing and returning functions like data.
let us consider abstracting collection iteration mechanics. STL provides many types of containers for storing a collection of data with iterators to access the data. The iterator's are used to iterate over all the elements in the container to perform operations on every element.
Example:
// A collection (vector) of 10 integers with value 1
std::vector<int> integer_collection(10, 1);
for(std::vector<int>::const_iterator it = integer_collection.begin(); it != integer_collection.end(); it++)
{
std::cout << *it << std::endl;
}
With higher order programming, the above code can be DRY'ed to the code below wherein all the iteration mechanism is abstracted into the for_each
function. The third parameter passed to for_each
is a lambda function which is called by for_each
for every element in the vector. the lambda accepts an integer and performs the required operation.
std::for_each(integer_collection.begin(), integer_collection.end(), [](int &n){
std::cout << n << std::endl;
});
Defining functions that take lambda's as parameters:
In the above example, what could be the prototype of
for_each()
i.e, What is the type of the lambda function?1. The lambda's type can be prototyped with generic templating.
template<typename L>
void function(L lambda)// pass the right lambda!!
{
lambda(10);// Beware, Compiler could complain if the lambda doesn't accept int parameter.
}
2. The lambda's without capture variables can be cast into function pointers.
void function(void (funptr*) (int x)) // lambda that takes int parameter returning void
{
funptr(10); // call lambda
}
3. The lambda's type can be automatically deduced in C++11 with
auto
keyword.void function(auto lambda)
{
lambda(10);
}
4. The lambda's type can be defined with
std::function
defined in <functional>
header from C++11.void function(std::function<void(int)> lambda)// lambda that takes int parameter returning void
{
lambda(10);
}
The lambda can not only be used as a functor object which can be passed to other functions. Closure's can be constructed i.e, the functions can access the variable's in the enclosing scope.
Simplified Syntax:
[capture variable's list - optional](additional parameter's - optional) { function body }
A simple example:
{
int a, b, c;
func([a, &b] (int x, double y) {
// Call me back with a int and double
});
}
The function func takes a lambda parameter which captures the variable
a
by value and b
by reference and takes parameters x
and y
.It should be noted that the advantages gained with lambda's can be achieved with function objects too. Thus, lambda's are syntactic sugar which eliminate the need to write function objects elsewhere in the code which is expected to be used only once, keeping the code DRY and in writing elegant functional programs.
No comments:
Post a Comment