

Lambda-style anonymous functions for C++ in less than 500 lines of code - adg001
http://matt.might.net/articles/lambda-style-anonymous-functions-from-c++-templates/

======
lolcraft
_To pull this off, the implementation exploits templates, operator overloading
and function pointers (but, remarkably, not a single macro) to construct a
type-safe domain-specific embedded language._

Yes, "exploiting" is exactly the word I was looking for. Cool hack, though.

------
jheriko
This is interesting, but I'm not upvoting it... I wrote something similar for
dealing with calculus on tensor fields a few years back and most compilers
I've written use something similar for dealing with expressions.

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...

~~~
fadmmatt
(Article author here.)

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...](http://matt.might.net/articles/church-encodings-demo-in-scheme/)

If programming languages were about computational power, we would have stopped
with Fortran.

Programming languages are about the freedom of expressions.

~~~
jheriko
"If programming languages were about computational power, we would have
stopped with Fortran.

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.

~~~
eru
> [...] but in practice they produce faster executables [...]

C++ is faster than Fortran?

~~~
jheriko
In all tests I've done - yes it is. Although I haven't tested every compiler
and platform for obvious reasons.

------
tbrownaw
Very cool, but fortunately soon to be unnecessary:
[http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_...](http://en.wikipedia.org/wiki/C%2B%2B0x#Lambda_functions_and_expressions)

Also, real currying in C++0x: <http://pastebin.com/KRraz7iU>

~~~
fadmmatt
Neat; but C++0x does this:

[](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.

~~~
tbrownaw
And those few extra characters give you an _enormous_ amount of flexibility,
such as not needing to define wrapper template specializations for all your
types, not needing to have extra variables sitting around to define your
argument placeholders, and being able to use more than just simple
expressions.

------
teamonkey
Oleg's method is shorter.

<http://okmij.org/ftp/cpp-digest/Functional-Cpp.html>

~~~
stingraycharles
I'm not sure whether it's more readable though, which imho is more important.

------
jcl
As written, though, isn't this limited to only multiplication and addition? If
you wanted to include, for example, a function call in your anonymous
function, wouldn't that require a pile of Var<>-based function overloads?

------
shin_lao
Or you can use Visual Studio 2010 and use C++ lambdas.

Nice post nevertheless.

------
Jach
This is so much nicer than Boost's stuff. Quite the exploit but still awesome,
it'll probably go into my next side-project.

~~~
sorbits
Though it doesn’t work with the standard algorithms.

For example you can’t do stuff like:

    
    
        std::transform(first, last, lambda<int> (x) --> 2*x);

~~~
Jach
What are you talking about? You're missing an arg in your transform() call.

    
    
      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.

------
rbanffy
Less than 500 lines of C++ code is very little? A lot? I don't know what to
make of it.

~~~
eru
500 lines is not a lot in C++. Or is it?

------
wrs
Oh my. It's true what they say about teaching a pig to dance.

------
confuzatron
Less than 500 lines of code. More than 500 lines of compiler errors if you get
a character wrong somewhere. ;)

~~~
dirtyaura
Yes. However, in my experience, on _a small team_ , benefits of readable code
by using templates to implement DSLs in C++ still outweighs burden of prosaic
error messages. You quite quickly learn to pattern match error messages to
find the real problem.

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.

~~~
sreque
If you've ever tried starting a debugger in a program that uses the Boost
Lambda library you might disagree. My program was only a few hundred lines
long, a toy, but I for the first time had to turn pagination on in gdb to view
my program's stacktrace because the it filled two entire screens! Even worse,
compile times on my program were ridiculously high and I was wasting a ton of
my time in long compile-run feedback cycles. Eventually I threw my hands up in
disgust and started hand-rolling my own structs. Compile times dropped to
under a second and I was able to easily spot my mistakes in the debugger.

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.

~~~
loup-vaillant
All this can be traces back to a root problem: using, maybe even needing, C++.
Solution: don't use C++, or run away. (And spread the word[1]) I am dead
serious: I don't follow my own advice, and that makes me miserable at work.

[1]: <http://yosefk.com/c++fqa/> (I actually learned quite a few things there)

~~~
_delirium
I second the recommendation of Yosef K's FQA. It's not just an anti-C++ rant,
but a pretty detailed explanation of a lot of C++'s features, interactions
between features, and corner cases (and how those will bite you in the ass).

