AUG
29
2014

Lazy declarative programming in C++11

make does it, Haskell does it, spreadsheets do it, QML can do it and below I explain how to do it with C++11: declarative programming. And not just any declarative programming, but my favorite kind: lazy evaluation.

I have written a few C++ classes that wrap imperative C and C++ functions into functional expressions. A simple example illustrates the difference between the common imperative programming and declarative programming.

/**
 * This is our business logic.
 */
int sum(int a, int b) {
   return a + b;
}
/**
 * In the imperative example, c and d are just storage locations for the results.
 */
void imperative() {
    int a = 3;
    int b = 4;
    auto c = sum(a, b);
    auto d = sum(a, c);
    // correct
    std::cout << a << " + " << b << " = " << c << std::endl;
    std::cout << a << " + " << c << " = " << d << std::endl;
    a = 4;
    // error: c and d have not been updated
    std::cout << a << " + " << b << " = " << c << std::endl;
    std::cout << a << " + " << c << " = " << d << std::endl;
}
/**
 * In the lazy example, c and d are defined by the function sum()
 * and the actual values of c and d are determined when these variables
 * are accessed. Any C or C++ function can be used, but the outcome
 * should depend only on the input values.
 */
void lazy() {
    InputValue<int> a = 3;
    InputValue<int> b = 4;
    auto c = makeLazy(sum, a, b);
    auto d = makeLazy(sum, a, c);
    std::cout << a << " + " << b << " = " << c << std::endl;
    std::cout << a << " + " << c << " = " << d << std::endl;
    a = 4;
    std::cout << a << " + " << b << " = " << c << std::endl;
    std::cout << a << " + " << c << " = " << d << std::endl;
}

The function makeLazy() which turns imperative functions to functional use, relies on a new feature in C++: variadic templates. Variadic templates give C++ great flexibility in the use of functions in templates. The example above shows that the functions can be chained.
The biggest advantage of this style of programming is that the programmer does not have to worry about whether the results are up to date. Programming like this feels like writing a spreadsheet: you give the logic and the computer takes care of how and when to get the result. It is nice to see that clean lazy functional programming can be done in C++ too.