I have a top level lambda function and then there are couple of nested lambda functions inside this lambda.
Is it a good idea to nest lambdas inside other lambdas? Are there any performance implications?
For e.g.
auto Multiplier1 = []() -> int
{
auto Multiplier2 = [](int i) -> int
{
auto Multiplier3 = [](int i) -> int
{
return i * 2;
};
std::cout << "Calling another lambda 2\n";
return Multiplier3(i * 100);
};
int i = 10;
std::cout << "Calling another lambda 1\n";
int ret = Multiplier2(i);
return ret;
};
int ret = Multiplier1();
std::cout << ret << "\n";
In the example above, I can re-factor Multiplier2 and Multiplier3 into separate functions. Is that a better approach compared to this?
I am modifying a code which is already in production and hence, I was in a dilemma whether to re-factor it into separate functions or manage using lambda functions.
Python allows lambda nesting, i.e., you can create another lambda function inside a pre-existing lambda function. For nesting lambdas, you will need to define two lambda functions – an outer and an inner lambda function. When the outer lambda is called, the inner lambda creates a function.
Lambda functions are inline functions and thus execute comparatively faster.
A lambda object must not outlive any of its reference captured objects. Lambda expressions may capture objects with automatic storage duration from the set of enclosing scopes (called the reaching scope) for use in the lambda's function body.
Asking about performance implications as a result of expression of coding style is always the wrong question.
The compiler, when optimising, considers expressed intent, not the layout of your code.
This example is extreme but it's worth showing you the code produced by gcc with compiler option -O2
.
Refactoring the code above to remove the noise that will be produced by the use of cout
:
auto Multiplier1 = []() -> int
{
auto Multiplier2 = [](int i) -> int
{
auto Multiplier3 = [](int i) -> int
{
return i * 2;
};
return Multiplier3(i * 100);
};
int i = 10;
int ret = Multiplier2(i);
return ret;
};
extern void emit(int);
int main()
{
int ret = Multiplier1();
emit(ret);
}
compiling with gcc -S -O2 -std=c++14
yields:
main:
subq $8, %rsp
movl $2000, %edi
call emit(int)
xorl %eax, %eax
addq $8, %rsp
ret
Notice that the optimiser has seen through all the code and realised that the only course of action this code could ever take (that matters) is to call the function emit
with the argument value of 2000.
The lesson is always that one should express intent elegantly (i.e. in a way that can be understood and maintained easily) and allow the compiler to do its job of emitting code that implements that intent in the least time and/or code size.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With