What is this C++14 construct called which seems to

2020-06-12 03:02发布

This is a follow-up question on this one: Lambda-Over-Lambda in C++14, where the answers explain the code.

It is about a lambda that creates another lambda which when called, calls the passed lambda and passes the return value to the original lambda, thus returning a new instance of the second lambda.

The example shows how this way lambdas can be chained.

Copy from the original question:

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

}

Is there already a name for this construct and if not what should it be called? Does it resemble constructs in other languages?

Remark: I'm not interested in whether it is actually useful.

标签: c++ lambda c++14
3条回答
你好瞎i
2楼-- · 2020-06-12 03:35

I looked around a bit and turns out the main functionality is reordering the function calls as explained in the answers to the original question.

So world(hello(stdout)); is rewritten to terminal(stdout)(hello)(world); which more generally could be written as compose(stdout)(hello)(world);.

I think it is only useful with decent partial application which lambdas provide a little bit, so we could have compose(4)([](int x){ return x + 7; })([](int x){ return x * 2; })([](int x){ return x == 22; }); which should return true if my calculation (and blind coding) is any good.

or to emphasize the partial application:

auto add7 = [](int x){ return x + 7; };
auto dbl = [](int x){ return x * 2; };
auto equal22 = [](int x){ return x == 22; };
assert(compose(4)(add7)(dbl)(equals22));

1 major issue with this implementation is probably that the result can't be evaluated because in the end a lambda is returned, so the construction in this answer might be better suited (function separated by comma instead of parenthesis).

查看更多
Juvenile、少年°
3楼-- · 2020-06-12 03:42

As far as I know there is no "official" name, yet.

Suggestions:

  • Lambda chain
  • Lambda sausage
  • Curry sausage
查看更多
贼婆χ
4楼-- · 2020-06-12 03:51

terminal(x) returns an applicator that method-chains its return value into terminal for repeated invocation.

But we could instead generalize it.

Suppose you have a function F. F takes an argument, and stuffs it on a stack.

It then examines the stack. If the top of the stack, evaluated on some subset of the stack, would work for invocation, it does it, and pushes the result back onto the stack. In general, such invocation could return a tuple of results.

So:

F(3)(2)(add)(2)(subtract)(7)(3)(multiply)(power)

would evaluate to:

((3+2)-2)^(7*3)

Your terminal does this with 0 argument functions (the first argument) and with 1 argument functions (every argument after that), and only supports 1 return value per invocation.

Doing this with a lambda would be tricky, but what I described is doable in C++.

So one name for it would be stack-based programming.

查看更多
登录 后发表回答