Working with C++0X/C++11: Lambdas – part 3 – introducing closures

Closure

In computer science, a closure (also lexical closure, function closure, function value or functional value) is a function together with a referencing environment for the non-local variables of that function. A closure allows a function to access variables outside its typical scope. Such a function is said to be “closed over” its free variables. The referencing environment binds the nonlocal names to the corresponding variables in scope at the time the closure is created, additionally extending their lifetime to at least as long as the lifetime of the closure itself. When the closure is entered at a later time, possibly from a different scope, the function is executed with its non-local variables referring to the ones captured by the closure.

(source: Wikipedia)

The most compelling use (in my opinion) for lambdas is for creating closures out of simpler lambdas. Once you understand that a lambda can return another lambda, you suddenly have a whole new toolkit at your disposal.

Let’s suppose that you want to write a set of parsing routines that you can use to create a command line parsing utility. Typically you’ll just find a switch statement that parses the command line in a C++ program, but basically you just need;

1) a “key” (i.e. the key or command that indicates you want to alter some particular behavior in the program).
2) some way of indicating that change to the program – typically through the use of a variable.

You can write an much more extensible utility using lambdas to hide behavior and variable references. It gets tricky here because the input is a string (part of the command line), and the result is that a “variable” gets set or modified. It’s tricky because the “variable” is the part that typically needs specialization. However this is where lambdas excel – we can use partially specified lambdas to hide the underlying variable. In other words, we’re going to use one lambda to create another, hiding some state inside.

So let’s create a function that takes an integer reference and a const string pointer, parses the string to an integer value, and stores it in the int. So far, so good. The tricky part is we’re going to return a function pointer to a function that takes the const string pointer as it’s argument. It looks like this;

.
     auto store_int =
    [](int& x) -> function < void (const char*) >
       {
        return [&x](const char* y){ stringstream(y) >> x; };
        };
.

Let’s go over this in detail;

.
    auto store_int = 
.

I’m storing something (TBD but I know it’ll be a function pointer) in a variable named “store_int”. The next part is;

.
    [](int& x)
.

I’m storing a lambda that takes an int address and doesn’t capture any scope (it’s just a function that takes an int reference). Now we need to specify what this function returns;

.
     -> function< void (const char*) >
.

… it returns a function pointer (the keyword function) and this function returns void and takes a const char pointer as an argument. In other words, I’m creating a function that takes an integer address as its argument, and this function then returns a function pointer to a function that takes a const char* as an argument and returns void. Now I just need to write the body of the lambda; This is going to be *another* lambda!

.
     { return [&x](const char* y) { stringstream(y) &gt&gt x; }; };
.

So I start the lambda body with an open curly brace, then I return a new lambda which I create in place; This inner lambda takes the reference to argument “x” (which was passed in as an argument to the outer lambda). Pass by reference allows it to modify the value in “x”; The inner lambda takes a const char pointer as its function argument. This argument comes from the argument list of the inner lambda I’m creating. Finally in the body of the inner lambda – I use stringstream to convert the string to an int through the right shift operator (it’s less error prone than atoi, and it works to convert to most data types, I use stringstream when I need to parse strings). So this is where the two function arguments actually connect, I parse the string and store it in the integer address. But these are provided in two separate function calls – the outer one and the inner one.

This is the trick – I create one function that takes a reference to the variable I want to store the command line parameter result in. This function encapsulates that integer reference up in another function that takes a char pointer. This is what gets returned. The integer reference is totally hidden from the outside. When you call this function the string argument gets parsed and stored in the referenced integer. This is a closure. Sometime after I create this function, I can call it with a const char* argument, and that string will get converted to an integer and stored in the integer address that was passed in when I created the closure.

I’ll post how you’d use this in a more complete implementation in my next post. That will make the magic of closures much more obvious. But to wrap up, let’s look at using what we created above;

.
     int myInt;   // create an integer

    // pass the integer to store_int
     auto mfunc = store_int(myInt);
    // mfunc is a function taking a const char*
    // the reference to myInt is hidden inside mfunc

     mfunc("4"); // use it, the string gets parsed
    // myInt gets set to 4
.

So we’ve used closures to hide a reference to a variable and its type. Next time we’ll use this not only to hide variable address and type information, but to hide behavior modifications as well.

This entry was posted in C++0X/C++11. Bookmark the permalink.