Lambda-Over-Lambda in C++14
How following recursive lambda call ends/terminates ?
#include <cstdio>
auto terminal = [](auto term) // <---------+
{ // |
return [=] (auto func) // | ???
{ // |
return terminal(func(term)); // >---------+
};
};
auto main() -> int
{
auto hello =[](auto s){ fprintf(s,"Hello\n"); return s; };
auto world =[](auto s){ fprintf(s,"World\n"); return s; };
terminal(stdout)
(hello)
(world) ;
return 0;
}
What am I missing over here ?
Running code
It's not a recursive function call, look at it step-by-step:
-
terminal(stdout)
- this simply returns a lambda which has capturedstdout
- The result of 1. is called with the lambda
hello
, which executes the lambda (func(term)
), the result of which is passed toterminal()
, which simply returns a lambda as in 1. - The result of 2. is called with the lambda
world
, which does the same as 2, this time the return value is discarded...
The call itself is not recursive. It returns a function object which, if called, will call terminal
again to generate yet another function object.
So terminal(stdout)
returns a functor which captures stdout
and can be called with another function object. Calling it again, (hello)
, calls the hello
functor with the captured term stdout
, outputting "Hello"
; the calls terminal
and returns another functor which this time captures the return value of hello
- which is still stdout
. Calling that functor, (world)
, just the same again, outputting "World"
.
The key here is to understand that this is valid:
world(hello(stdout));
and will print "Hello World". The recursive series of lambdas can be unrolled as
#include <cstdio>
auto terminal = [](auto term) // <---------+
{ // |
return [=] (auto func) // | ???
{ // |
return terminal(func(term)); // >---------+
};
};
/*
terminal(stdout) -returns> anonymous_lambda which captures stdout (functor)
anonymous_lambda(hello) is called, func(term) is hello(stdout) and prints "Hello" and returns stdout, the anonymous_lambda -returns> terminal(stdout)
(the above 2 lines start again)
terminal(stdout) is called and -returns> anonymous_lambda which captures stdout (functor)
anonymous_lambda(world) is called, func(term) is world(stdout) and prints "World" and returns stdout, the anonymous_lambda -returns> terminal(stdout)
terminal(stdout) is called and -returns> anonymous_lambda which captures stdout (functor)
nobody uses that anonymous_lambda.. end.
*/
auto main() -> int
{
auto hello =[](auto s){ fprintf(s,"Hello\n"); return s; };
auto world =[](auto s){ fprintf(s,"World\n"); return s; };
world(hello(stdout));
terminal(stdout)
(hello)
(world) ;
return 0;
}
Coliru example