AUG
29
2014
|
Lazy declarative programming in C++11make 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. |
![]() |
Comments
Hello! This is a very cool
Hello! This is a very cool concept, but I think you are confusing laziness with something like Functional Reactive Programming (FRP).
Laziness means that an expression is not evaluated until the first time it is needed. However it does not mean that the expression will be recalculated when it's arguments change. For example in Haskell the program
will output
just like imperative().
Note the unusual ugliness of this code - this is because it uses actual mutable variables to closely mimic the C++ code. Laziness means just that the actual computation of variables c and d is delayed until we force it (by printing them). After that the result is cached and will not be recomputed.
Now, spreadsheets do it, Haskell can do it (with special libraries), QML does it, React.js does it, your code does it, Elm does it: Reactive programming. You are right that it is a kind of declarative programming. Some RP implementations are very flexible, as they allow values not only to depend on other values, but also to be a function of time or change based on incoming events - and the framework will take care of what to recompute and when to recompute. This paradigm is especially useful for stuff like user interfaces, eg. with React.js you do not have to update the DOM when the state of your application changes, because it will happen automatically.
Re:
You are right. Lazyness is not the right word. Functional reactive programming is indeed more accurate.
Source files
Thanks for the post. The link to the 'a few C++ classes' seems to be broken. Can you post the files for makeLazy()?
Thanks again
makeLazy.h
It's just one header file.