7

浏览一些互联网板我遇到了这个小挑战:

“用你喜欢的语言实现一个递归匿名函数”

显然,使用 std::function/function 指针很容易。

我真正感兴趣的是,如果不将 lambda 绑定到标识符,这是否可行?

类似的东西(忽略明显的无限递归):

[](){ this(); }();
4

4 回答 4

5

当然,在 C++ 中,要调用任何函数,您必须将其绑定到某处的标识符,这仅仅是由于语法限制。但是,如果您接受参数足够未命名,则可以在 C++ 中创建一个 y-combinator 版本,该版本可以很好地递归而无需“命名”。

现在,这真的很难看,因为我不知道如何为递归 lambda 做 typedef。所以它只是使用了很多演员滥用。但是,它可以工作并打印,FLY!!直到由于堆栈溢出而出现段错误。

#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);
    });
}

这两个 lambda 表达式是未命名的,因为它们都没有被显式分配给任何地方的名称。第二个 lambda 是真正的主力,它基本上通过使用第一个 lambda 以参数的形式获取对自身的引用来调用自身。

以下是您将如何使用它来做一些“有用的”工作:

#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;
}
于 2013-03-11T18:44:47.630 回答
3

你被允许作弊吗?

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

它是递归的——至少是间接的。

否则,不,没有办法在不给它命名的情况下引用 lambda 本身。

于 2013-03-11T17:46:16.210 回答
1

没有功能/方法的标识符,是否足够接近!?

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

打电话

A{}(); // Thanks MooningDuck
于 2013-03-11T17:58:24.070 回答
0

我似乎想出了自己的解决方案:

#include <iostream>

int main()
{
    std::cout<<"Main\n";
    [&](){
        std::cout<<"Hello!\n";
        (&main+13)();
         }();
}

第一次调用 cout 只是为了表明它没有调用 main。

我通过反复试验得出了 13 个偏移量,如果有人能解释为什么它是这个值,那就太好了。

于 2013-03-11T19:37:23.880 回答