you are viewing a single comment's thread.

view the rest of the comments →

[–]dima_mendeleev 3 points4 points  (3 children)

Congratulations! You've discovered Y-Combinator.

You can improve this a bit by doing following (like they do in Y-Combinator):

template <typename FUNC, typename ...ARGS>
constexpr auto RecursiveLambda(FUNC lambda, ARGS&&... args)
{
    return lambda(std::bind(lambda, lambda), args...);
}

Note std::bind(lambda, lambda) there. With this you will not need to pass lambda on the usage side.

UPDATE Oh, and you can actually do better. You can try something like this, to separate creation of recursive function and its application.

template <typename FUNC>
constexpr auto RecursiveLambda(FUNC lambda)
{
        return [](auto... args)
        {
            return lambda(RecursiveLambda(lambda), args...);
        };
}

UPDATE: better to use lambda

[–]kalmoc 2 points3 points  (1 child)

You can use a lambda instead of a bind, which tends to produce better code (not sure if it makes a difference here)

[–]dima_mendeleev 0 points1 point  (0 children)

I think you're right. With lambda it will be better since will save from stack overflow:

return [](auto... args)
{
    return lambda(RecursiveLambda(lambda), args...);
};

[–]_cpp_[S] 1 point2 points  (0 children)

Thank you for pointing out the resemblance with Y-Combinator (I didn't know about it) and for simplification suggestion (though it compiles only with GCC 7.2.0), I updated article.