Page Collection for ^2011-09

2011-09-07 CPlusPlus0X

Lambda expressions

For defining small functions at the very spot they are used C++ introduces lambda expressions. A lambda expression is like a short function that can be used where a normal function would be called. Here is an example of a predicate functions that returns true for odd numbers:

[](int x) { return x % 2 == 1; }

This specifies a lambda expression taking one int parameter. The return type is defined by the type of the return statement. Yet a place where compact notation has been chosen. It can be put to use in a count_if algorithm like this:

list<int> numbers {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int numberOfOdd = count_if(numbers.begin(), numbers.end(), [](int x) { return x % 2 == 1; });

No need to define a local predicate functions. The lambda expression can be used right in place.

But there is more. We just saw that a lambda can take arguments but it can also bind to variables in the scope of its creation like this:

int sum = 0;
for_each(numbers.begin(), numbers.end(), [&sum](int x) { sum += x; });

The variable sum is available in the lambda and it is accessed by reference. The [&sum] notation in the beginning of the lambda expression defines this binding.

In the next posting we'll look more into the closure aspects of lambdas.

2011-09-15 CPlusPlus0X

More on Lambdas

As we saw in the example with computing the sum we could in the lambda bind a variable from the defining scope. This is also known as a closure. The functions is closed over its free variables. That is great, it has fancy name, can we look at more ways how to use it?

One new aspect is if we look at capture by value. In the sum example we bound sum by reference so we could update it inside the lambda. If we want the value at the creation time of the lambda we capture by value instead. It looks like this:

[var] (... // capture variable var by value
[=] (...   // capture all variables by value
int divBy = 2;
auto divBy2 = [divBy] (int x) { return x / divBy; };

divBy = 4;
auto divBy4 = [divBy] (int x) { return x / divBy; };

assert(4 == divBy2(8));
assert(2 == divBy4(8));

Yes, the first lambda divides by 2 and the second by 4. All because divBy is captured by value when we defined the lambda.

To go further, we can even bind this. So accessing and calling members from a lambda expression is possible. Let us define a class (using a struct to make the example less verbose)

struct Name 
{
   string name;
   void me() { cout << "I'm: " << name << endl; }
   function<void()> callMe() { return [&]() { me(); }; }
};

The first function member me is easy to understand. It prints the name of the object.

The second member callMe requires some explanation. First it introduces std::function. Let us settle for now that it declares a callable type taking no parameters and returning void. The lambda itself binds all members by reference and calls the member me.

Using it can look like this:

Name al {"Al"};
auto gl = al.callMe();
gl();    // Prints "I'm: Al"

This is like a function object but created with less typing.