Example of a Practical Use for Lambdas

Viewed 6412

I’ve recently started the process of researching lambdas for personal use. I’ve been coding for a few years now, I’ve released multiple products into the wild, and yet, I’ve never found myself needing to use lambdas. I’ve read the other stack exchange answers for various lambda questions, but I haven’t found an explanation that shows a dead-simple example that really drives the idea that lambdas are necessary (for some situations). After doing a bit of research, I’m not convinced that some of the specific uses of lambdas can’t be implemented with standard functions, however, that doesn’t mean much because my scope of the topic is extremely limited.

Can someone provide a rather simple use case for lambdas that demonstrates how they can be more powerful than typical functions (in the correct situations)?

3 Answers

C++ was Turing complete long before C++11. Lambdas aren't there for making something impossible into a possibility. You can accomplish much without them. They are there to streamline certain pieces of code.

For instance, to allow on-the-fly creation of functors to the standard algorithm library. Sure you can define one on your own. But that requires going outside your funcion, and naming a new type. A whole lot of boilerplate for a simple call to std::transform, as an example.

They keep code localized, don't require you to pollute any namesapces, and are easy to use once you get the hang of it.


As a bonus, in his talk about functional C++, Kevlin Henney reduces an example function from a framework into something that really cries out "use a lambda". So to borrow a little from his talk, consider a command registration function:

void register_command(std::string cmdName, std::function<void()> f);

You want to register a command that just turns on a light bulb. How much boilerplate would you need to write for a custom functor, compared to the following?

register_command("Turn On Light-bulb", [&light_controller]() {
  light_controller.on();
});

Ponder that, and which code base you'd personally rather maintain.

Everything that can be done with lambdas nowadays could have been done in C++03 by handwriting a struct/class with an overloaded operator() (commonly called "functors"). There was a huge issue with that: lack of terseness and lack of locality.

Imagine passing a templated predicate to something like std::find_if in C++03:

struct predicate
{
    template <typename T>
    bool operator()(const T& x) { return boop(x); }
};

void foo()
{
    something(std::find_if(c.begin(), c.end(), predicate()));
}

You need to:

  • Define predicate somewhere, potentially far away from where it's used.

  • Have boilerplate for the struct and the operator() overload.

  • Jump around in the source code while reading it, to understand what predicate is doing.

Compare that to a C++14 generic lambda:

void foo()
{
    something(std::find_if(c.begin(), c.end(), 
        [](const auto& x){ return boop(x); });
}

Boom. Everything is there, local, with minimal boilerplate.


Lambdas are not magic. They purely are syntactic sugar. But I'm my opinion, they're "syntactic sugar to handwritten structs" as "C++ is syntactic sugar to C".

They change the way you write code, they make functional paradigms (e.g. higher-order functions) viable, and can make your code more powerful and safer.

We can possible do almost everything without using lambdas. However lambdas are introduced to support functional programming and is useful in many cases.

I've recently used it in threads and it made my life easier. Here is a very simplified version

int main() {
    int value = 0;

    thread th { [=](){ 
        cout<<"I am inside thread fn Value = "<<value<<endl;
    }};

    th.join();
}

There are two obvious benefits over here

  1. The lambda prevented creation of a global or class static function
  2. I don't need to pass parameters to threads ( A complex thing to do), because lambda closure takes care of that.

So there are few cases where lambda may be a better option, but it doesn't mean that we can't do the same with functions

Related