+31  A: 

I don't think it's nearly as much about the computational performance as increasing the expressive power of the language.

JaredPar
A programming language without lambda is like a day without sunshine.
Brian
@Brian, you live in Seattle, shouldn't be a big change ;)
JaredPar
+8  A: 

Lambdas are syntactic sugar for functor classes, so no, there is no computational benefit. As far as the motivation, probably any of the other dozen or so popular languages which have lambdas in them?

One could argue it aids in the readability of code (having your functor declared inline where it is used).

Terry Mahaffey
+8  A: 

IMO, the most important thing about lambda's is it keeps related code close together. If you have this code:

std::for_each(begin, end, unknown_function);

You need to navigate over to unknown_function to understand what the code does. But with a lambda, the logic can be kept together.

R Samuel Klatchko
Ideally, "unknown_function" would be named well enough to give you a good idea of what it does.
Fred Larson
@Fred: If you have the lambda definition right there at the point of use, the reader is spared the effort of wondering if the function is well-named or not, and the writer is spared the effort of having to pick a good name for a trivial operation that's only going to be used in one place.
Jim Lewis
@Jim Lewis: Agreed. I don't think lambdas are a bad thing. But at the same time I don't think it's always a bad thing to move a loop body into a functor. As always, use what's best for your situation.
Fred Larson
"move a loop body into a functor" - not always, of course. But if the code isn't used elsewhere (and you want to indicate that this is the case), the boilerplate of an `operator()` in a class in an anonymous namespace in C++03 is kind of boring ;-)
Steve Jessop
+23  A: 

The benefit is what's the most important thing in writing computer programs: easier to understand code. I'm not aware of any performance considerations.

C++ allows, to a certain extend, to do Functional Programming. Consider this:

std::for_each( begin, end, doer() );

The problem with this is that the function object doer

  1. specifies what's done in the loop
  2. yet somewhat hides what's actually done (you have to look up the function object's operator()'s implementation
  3. must be defined in a different scope than the std::for_each call
  4. contains a certain amount of boilerplate code
  5. is often throw-away code that's not used for anything but this one loop construct

Lambdas considerably improve on all these (and maybe some more I forgot).

sbi
+2  A: 

Well, compare this:

int main () {
    std::vector<int> x = {2, 3, 5, 7, 11, 13, 17, 19};

    int center = 10;
    std::sort(x.begin(), x.end(), [=](int x, int y) {
        return abs(x - center) < abs(y - center);
    });

    std::for_each(x.begin(), x.end(), [](int v) {
        printf("%d\n", v);
    });

    return 0;
}

with this:

// why enforce this to be defined nonlocally?
void printer(int v) {
    printf("%d\n", v);
} 

int main () {
    std::vector<int> x = {2, 3, 5, 7, 11, 13, 17, 19};

    // why enforce we to define a whole struct just need to maintain a state?
    struct {
        int center; 
        bool operator()(int x, int y) const {
            return abs(x - center) < abs(y - center);
        }
    } comp = {10};

    std::sort(x.begin(), x.end(), comp);

    std::for_each(x.begin(), x.end(), printer);

    return 0;
}
KennyTM
I don't think the second is even legal. AFAIK function-local types must not be used as template arguments. Or did C++2003 fix this embarrassing problem?
sbi
@sbi: Templates? What templates? Anyway, the 2nd piece is still compiled in c++0x mode (note the use of initializer list), as the OP just ask for the motivation of lambda expressions.
KennyTM
`std::sort()` and `std::for_each()` are the templates @sbi referred to. C++0x lifts that restriction though.
Georg Fritzsche
@Georg: I see, thanks.
KennyTM
+4  A: 

There's no performance benefit per se, but the need for lambda came as a consequence of the wide adoption of the STL and its design ideas.

Specifically, the STL algorithms make frequent use of functors. Without lambda, these functors need to be previously declared to be used. Lambdas make it possible to have 'anonymous', in-place functors.

This is important because there are many situations in which you need to use a functor only once, and you don't want to give a name to it for two reasons: you don't want to pollute the namespace, and in those specific cases the name you give is either vague or extremely long.

I, for instance, use STL a lot, but without C++0x I use much more for() loops than the for_each() algorithm and its cousins. That's because if I were to use for_each() instead, I'd need to get the code from inside the loop and declare a functor for it. Also all the local variables before the loop wouldn't be accessible, so I'd need to write additional code to pass them as parameters to the functor constructor, or another thing equivalent. As a consequence, I tend not to use for_each() unless there's strong motivation, otherwise the code would be longer and more difficult to read.

That's bad, because it's well known that using for_each() and similar algorithms gives much more room to the compiler & the library for optimizations, including automatic parallelism. So, indirectly, lambda will favour more efficient code.

Fabio Ceconello
+3  A: 

Although I think other parts of C++0x are more important, lambdas are more than just "syntactic sugar" for C++98 style function objects, because they can capture contexts, and they do so by name and then they can take those contexts elsewhere and execute. This is something new, not something that "compiles faster/slower".

#include <iostream>
#include <vector>
#include <functional>
void something_else(std::function<void()> f)
{
        f(); // A closure! I wonder if we can write in CPS now...
}
int main()
{
        std::vector<int> v(10,0);
        std::function<void ()> f = [&](){ std::cout << v.size() << std::endl; };

        something_else(f);
}
Cubbi
No, it's not new. Lambdas capture by name at the point of definition. Exactly like function-objects with a constructor. Because lambda *are* syntactic sugar for function-object and could have been implemented as a source-to-source rewrite (see http://blogs.msdn.com/b/vcblog/archive/2008/10/28/lambdas-auto-and-static-assert-c-0x-features-in-vc10-part-1.aspx for examples of such rewrite). Well, it's not possible anymore in recent draft due to other reason : Stateless lambda must now decay to function pointer, so it's a bit different now than plain function-object, but not for the capture part.
Thomas Petit
Cubbi
@Cubbi: Not a syntax transformation, but a cleaner syntax for something that could be done previously. Hence syntactic sugar.
jalf
+1  A: 

"a neat development perk open for abuse by poor coders trying to look cool?"...whatever you call it, it makes code a lot more readable and maintainable. It does not increase the performance.

Most often, a programmer iterates over a range of elements (searching for an element, accumulating elements, sorting elements etc). Using functional style, you immediatly see what the programmer intends to do, as different from using for loops, where everything "looks" the same.

Compare algorithms + lambda:

iterator longest_tree = std::max_element(forest.begin(), forest.end(), [height]{arg0.height>arg1.height});
iterator first_leaf_tree = std::find_if(forest.begin(), forest.end(), []{is_leaf(arg0)});
std::transform(forest.begin(), forest.end(), firewood.begin(), []{arg0.trans(...));
std::for_each(forest.begin(), forest.end(), {arg0.make_plywood()});

with oldschool for-loops;

Forest::iterator longest_tree = it.begin();
for (Forest::const_iterator it = forest.begin(); it != forest.end(); ++it{
   if (*it.height() > *longest_tree.height()) {
     longest_tree = it;
   }
}

Forest::iterator leaf_tree = it.begin();
for (Forest::const_iterator it = forest.begin(); it != forest.end(); ++it{
   if (it->type() == LEAF_TREE) {
     leaf_tree  = it;
     break;
   }
}

for (Forest::const_iterator it = forest.begin(), jt = firewood.begin(); 
     it != forest.end(); 
     it++, jt++) {
          *jt = boost::transformtowood(*it);
    }

for (Forest::const_iterator it = forest.begin(); it != forest.end(); ++it{
    std::makeplywood(*it);
}

(I know this pieace of code contains syntactic errors.)

Viktor Sehr