Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call lambda without binding it to an identifier

Tags:

c++

c++11

lambda

Browsing some internet board I encountered this little challenge:

"Implement a recursive anonymous function in your favorite language"

Obviously this is easy using a std::function/function pointer.

What I'm really interested in is if this is possible without binding the lambda to an identifier?

Something like (ignoring the obvious infinite recursion):

[](){ this(); }();
like image 731
user1233963 Avatar asked Mar 11 '13 17:03

user1233963


3 Answers

Of course, in C++, to call any function you have to bind it to an identifier somewhere, simply owing to syntax constraints. But, if you will accept parameters as being sufficiently unnamed, then it is possible to create a version of the y-combinator in C++ which recurses nicely without being "named".

Now, this is really ugly because I don't know how to do a typedef for a recursive lambda. So it just uses a lot of cast abuse. But, it works, and prints FLY!! until it segfaults due to stack overflow.

#include <iostream>

typedef void(*f0)();
typedef void(*f)(f0);

int main() {
    [](f x) {
        x((f0)x);
    } ([](f0 x) {
        std::cout<<"FLY!!\n";
        ((f)x)(x);
    });
}

The two lambdas are unnamed in the sense that neither is explicitly assigned to name anywhere. The second lambda is the real workhorse, and it basically calls itself by using the first lambda to obtain a reference to itself in the form of the parameter.

Here's how you would use this to do some "useful" work:

#include <iostream>

typedef int param_t;
typedef int ret_t;

typedef void(*f0)();
typedef ret_t(*f)(f0, param_t);

int main() {
    /* Compute factorial recursively */
    std::cout << [](f x, param_t y) {
        return x((f0)x, y);
    } ([](f0 x, param_t y) {
        if(y == 0)
            return 1;
        return y*((f)x)(x, y-1);
    }, 10) << std::endl;
}
like image 92
nneonneo Avatar answered Oct 28 '22 14:10

nneonneo


Are you allowed to cheat?

void f(){
  []{ f(); }();
}

It's recursive - indirectly, atleast.

Otherwise, no, there is no way to refer to the lambda itself without assigning it a name.

like image 34
Xeo Avatar answered Oct 28 '22 14:10

Xeo


No identifier for functions/methods, Close enough or not !?

struct A
{
    void operator()()
    {
        [&]()
        {
            (*this)();
        }();
    }
};

To call

A{}(); // Thanks MooningDuck
like image 41
masoud Avatar answered Oct 28 '22 14:10

masoud