16

Why would one write a C++ lambda with a name so it can be called from somewhere? Would that not defeat the very purpose of a lambda? Is it better to write a function instead there? If not, why? Would a function instead have any disadvantages?

user9639921
  • 351
  • 2
  • 11
  • If one of the answers below fixes your issue, you should accept it (click the check mark next to the appropriate answer). That does two things. It lets everyone know your issue has been resolved to your satisfaction, and it gives the person that helps you credit for the assist. [See here](http://meta.stackexchange.com/a/5235) for a full explanation. – hellow Aug 10 '18 at 07:20

7 Answers7

11

One use of this is to have a function access the enclosing scope.

In C++, we don't have nested functions as we do in some other languages. Having a named lambda solves this problem. An example:

#include <iostream>

int main ()
{
    int x;

    auto fun = [&] (int y) {
        return x + y;
    };

    std::cin >> x;

    int t;
    std::cin >> t;
    std::cout << fun (fun (t));
    return 0;
}

Here, the function fun is basically a nested function in main, able to access its local variables. We can format it so that it resembles a regular function, and use it more than once.

Gassa
  • 8,546
  • 3
  • 29
  • 49
  • But in this case, as you only use the lambda one time, it could have been written and executed inline with the `std::cout <<`. The main advantage of not doing so is readability if the lambda is more than 1 line, and perhaps visible locality. – Gem Taylor Aug 09 '18 at 14:22
  • Can I write it as an inline function then if it needs surrounding variable? – user9639921 Aug 10 '18 at 04:48
  • @GemTaylor I've made an edit to incorporate your notions. – Gassa Aug 10 '18 at 07:46
  • @user9639921 There are other ways to achieve similarity to nested functions. [Here](https://stackoverflow.com/q/4324763/1488799) is a relevant question. – Gassa Aug 10 '18 at 07:47
  • @Gassa Yes, you can use the static member of a local class. That is what we used to have to do pre-'11. lambdas are better than that, and the compiler can optimise away the "function pointer" quite easily. Unsurprisingly, the reference implementation of lambdas is exactly this. – Gem Taylor Aug 10 '18 at 09:20
9

A good reason to use names is to express intent. Then one can check that the lambda does 'the right thing' and the reader can check the intent. Given:

std::string key;
std::map<std::string, int> v;

one can write the following:

std::find_if( v.begin(), v.end(), [&](auto const& elem){ return elem.first == key; } );

but it's hard to tell whether it does 'the right thing'. Whereas if we spell it out:

auto matches_key = [&](auto const& elem){ return elem.first == key; };

std::find_if( v.begin(), v.end(), matches_key );

it is clearer that we do want the equality comparison and the readability is improved.

Thomas
  • 4,980
  • 2
  • 15
  • 30
5

I see three things to consider when choosing between a named lamdba and a free function:

  1. Do you need variables from the surrouding scope? If yes, choose a lamdba and leverage its closure. Otherwise, go with a free function (because of 3.).
  2. Could the closure state equally well be passed as a function parameter? If yes, consider preferring a free function (because of 3.).
  3. Do you want to write a test for the callable and/or reuse it in multiple translation units? If yes, choose a free function, because you must declare it in a header file and capturing variables in a lamdba closure

    • is a bit confusing in a header file (though this is debatable, of course).

    • requires the types to be known. You can't therefore live with forward declarations of function parameters and return types to reduce compilation times.

lubgr
  • 37,368
  • 3
  • 66
  • 117
2

When your lambda is a recursive function by itself you have no choice but to give it a name. Also, an auto keyword won't suffice and you would HAVE to declare it using an std::function with the return type and the argument list.

Below is the example for a function that returns the Nth Fibonacci number:

std::function<int(int)> fibonacci = [&](int n) {
    if (n == 0 || n == 1) {
        return 1;
    } else {
        return fibonacci(n - 1) + fibonacci(n - 2);
    }
}

You have to give it a name in order to capture it with &. And auto won't work since lambda needs its to know its types before calling itself.

santahopar
  • 2,933
  • 2
  • 29
  • 50
1

This is basicly an opinion based question. It's up to you, whether you prefer functions or lambdas, they are equivalent. A lambda shines, when you need variables from the surrounding. You just can capture them instead of passing it as a parameter, that's neat.

But beside of that, there is no difference.

hellow
  • 12,430
  • 7
  • 56
  • 79
0

when tuning a C++ application, a named lambda is easier to tune/trace, as compared to an anonymous/unamed lambda

0

I always consider lamdas as a nicety - I did plenty of C++ coding without them before they were introduced. So in some ways, I don't consider that there are many shoulds or shouldn'ts surrounding them. They are there to use however they make your life easier.

One time I use named lamdas is to scope a function - i.e. the lamda is only going to be used within another function - perhaps it does something a little dangerous, that you don't want other functions to have access to or perhaps you don't want to pollute the namespace.

If your lamda is too long to be an easy one-liner, but you don't want it to be a available outside of your scope, then a named lamda is ideal way to produce tidy easy to read code.

Phil Rosenberg
  • 1,597
  • 1
  • 14
  • 22