Lambda-style anonymous functions for C++ in less than 500 lines of code
matt.might.net
matt.might.net
Yes, "exploiting" is exactly the word I was looking for. Cool hack, though.
This is different though, it doesn't let you solve any new problems that C++ can't already solve, and it also happens to produce slower expressions than, e.g. a function object or a function being pointed to.
If you want lambdas (which let you solve exactly no problems you can't already solve with C++) then use a language that supports them instead of shoehorning them in badly.
I'd recommend Haskell...
I'd love to use Haskell, but I'm helping out on an exascale DoE project, and C++ is all we're allowed to use. Ugh.
Of course, lambdas don't make C++ more powerful, but that's just reductio ad Turing tar-pit.
You can turn that argument around, too: there's no problem you can solve with C++ that you can't solve with lambdas alone:
http://matt.might.net/articles/church-encodings-demo-in-sche...
If programming languages were about computational power, we would have stopped with Fortran.
Programming languages are about the freedom of expressions.
Programming languages are about the freedom of expressions."
I strongly disagree, /some/ programming languages are about expressive power - others are about computational power.
We didn't stop with Fortran, we moved onto C then C++ - they might not be able to do anything more in the computer science theoretical sense, but in practice they produce faster executables, and in real world applications that means more computational power can be brought to bear on problems with these sorts of languages.
Maybe speed doesn't matter for your problem, or lambdas are an especially nice fit. Mainly I'm just worried that you are going to produce substandard code with this kind of mindset... good code is written with the language's strengths and weaknesses in mind, not to enable the flavour-of-the-month paradigm to be used in an extremely sub-optimal fashion.
C++ is faster than Fortran?
Also, real currying in C++0x: http://pastebin.com/KRraz7iU
Instead, we got a lot of (now somewhat wasted) effort on concepts. I like concepts in principle, but too many C++ people saw concepts as a way to write provable code and unreadable library documentation instead of as a way to simplify compiler error messages.
[](int x, int y) { return x + y; }
instead of this:
lambda<int> (x,y) --> x + y
Ironically, the template hack could be shorter in many cases.
Nice post nevertheless.
For example you can’t do stuff like:
std::transform(first, last, lambda<int> (x) --> 2*x); int nums[] = {1, 2, 3};
printf("nums: %i %i %i\n", nums[0], nums[1], nums[2]);
std::transform(nums, nums+3, nums, (lambda<int> (x) --> 2*x));
printf("new nums: %i %i %i\n", nums[0], nums[1], nums[2]);
Edit: And of course, there's the implemented map he gives in the example: int* incs = (lambda<int> (x) --> x + 1).map(3,nums);
The class needs a little bit of work obviously (like more operators overloaded), but it's pretty nice.We might be bitten this later when new guys and gals join the team. Code is very readable for being C++, but newbies might have hard first few weeks with these error messages.
You probably mean that the boundary between meaningful C++ programs and typos is not very well defined?
What was I doing? I was just writing a simple program to try to understand Boost's spirit parser, somewhat of a monstrosity in its own right, and thought I'd use the lambda library along with it. While we're on the subject of crazy DSL's in C++ templates, I ended up concluding that Flex together with Bison or Lemon are much more pleasant to use than Spirit if you don't need a full recursive descent parser.
Using C++ templates to implement crazy meta-languages might seem like a cool idea, and it is, but in practice I've found it to mostly be a waste of time and very unproductive.
What has worked? It's much better to produce detailed logs of some of the subsystems and analyze them. This way you get much better understanding of the big picture of what is happening. Why? In UI code (or event-driven code in general) state changes that cause bugs happen over time, not inside one step of an event loop. You just can't get the big picture of event-driven code with a debugger, which is optimized for going up and down callstack.
We have build a custom tracing library (and yes, it uses a lot of MACROs) that allows us to do select what is traced in a very granular level. I can proudly say that it's wonderful tool, every UI platform should ship with something like that.
By the way, tracing is also better for debugging parsers, their behavior often have similarities to event-driven systems
But you are right about compile times. Those get worse with templates.
[1]: http://yosefk.com/c++fqa/ (I actually learned quite a few things there)