11

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.

Community
  • 1
  • 1
stefaanv
  • 14,072
  • 2
  • 31
  • 53
  • Duplicate of [this question](http://stackoverflow.com/q/25338795/596781)? – Kerrek SB Sep 02 '14 at 09:13
  • @quantdev awesome. It appears it has the example copied verbatim. So maybe there's specifically something else he's looking for. **Edit** quantdev had linked to http://stackoverflow.com/questions/25618934/lambda-over-lambda-in-c14 – sehe Sep 02 '14 at 09:15
  • @sehe: how is this the duplicate of a "tuple continuator" question when there are no tuples involved and how is this construction called based on the original question? The code is copied from the question that I made a follow-up from as explained in the question. – stefaanv Sep 02 '14 at 09:28
  • @stefaanv Read ^^ - your question is rather late. Fortunately, others can countervote. I would, due to reasonable doubts, but I can't undo my own vote. – sehe Sep 02 '14 at 09:29
  • Also, the construct is very clearly associated with "continuation monad" in the linked dupe. By many. If there is any lingering doubt, that just means it has no generally accepted name (yet). The fact that the example there _happens_ to name "tuples", is exactly as relevant as that your sample names "terminal". It's a demonstration – sehe Sep 02 '14 at 09:31
  • @sehe: no, I don't see how this is clearly associated, except that they are both about lambda's in which lambd'a are returned. Well, my question may be answered if the construction turns out to be useful. – stefaanv Sep 02 '14 at 09:41
  • @sehe Reopened. That said, I don't really like these kinds of questions, primarily because they can't be properly googled for. – R. Martinho Fernandes Sep 02 '14 at 10:42
  • 1
    it looks a bit like a very weird version of currying. https://en.wikipedia.org/wiki/Currying – Alexander Oh Sep 02 '14 at 10:50
  • @Alex: I think it is more related to clojure's juxt (http://clojuredocs.org/clojure_core/clojure.core/juxt), although it is not the same. – stefaanv Sep 02 '14 at 10:55
  • @R.MartinhoFernandes: no that's the problem with google: you need a name to look up some concepts and here I'm asking whether there is alrready a name, possibly from another language. BTW: thanks for reopening. – stefaanv Sep 02 '14 at 11:00
  • @R.MartinhoFernandes: but you do have a point. I made the title a little bit better. – stefaanv Sep 02 '14 at 11:03
  • @stefaanv has also a bit of: https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Named_Parameter in it. – Alexander Oh Sep 02 '14 at 11:15
  • @Alex: yes, I was looking for that too, but the name escaped me. The main difference is that here, there is only 1 parameter which is chained over the functions. If it would be Named Parameter, then the solution would be convoluted, because your linked implementation is much simpler. – stefaanv Sep 02 '14 at 11:24
  • 1
    @stefaanv from here on I suggest you find a valid use case for this pattern and look in the internet for applications of this use case. it usually is being named in the process of the adoption. – Alexander Oh Sep 02 '14 at 12:01
  • _"What's In a Name"_ ~ William Shakespeare – P0W Sep 02 '14 at 15:49
  • Just stumbled into this article: http://chriskohlhepp.wordpress.com/lambda-over-lambda-in-cplusplus14/ which seems to be using lambda-over-lambda for similar constructs – sehe Sep 05 '14 at 09:55
  • @sehe: thanks, based on the name I think that this is the article that P0W got his question from. I'll definitively read it over the weekend. – stefaanv Sep 05 '14 at 11:45

3 Answers3

4

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).

Community
  • 1
  • 1
stefaanv
  • 14,072
  • 2
  • 31
  • 53
  • @BЈовић: No, you must be joking ;) – stefaanv Sep 02 '14 at 15:25
  • @BЈовић actually I like writing functional, but I find that doing it in C++ results in this sort of code too easily, hence the links to a more natural implementation. – stefaanv Sep 02 '14 at 15:34
3

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.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • stack-based programming is probably a lot more generalized, but it is a nice idea. The difference with method-chains is that in that case it's typically the object that is passed through it's member functions while here it is a separate parameter which is passed through free functions which is more according to functional programming. – stefaanv Sep 02 '14 at 14:02
  • @stefaanv `operator()` is a member function too! ;) – Yakk - Adam Nevraumont Sep 02 '14 at 14:53
  • Yep, this shows that there is more than one way to look at it. – stefaanv Sep 02 '14 at 14:59
0

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

Suggestions:

  • Lambda chain
  • Lambda sausage
  • Curry sausage
TobiMcNamobi
  • 4,687
  • 3
  • 33
  • 52
  • That's a novel way. Just, give it your own name. (Cue: "No, that's what the name is called") – sehe Sep 02 '14 at 11:11
  • @sehe "... and if not *how should it be called*?" (emphasis by me) was part of the question. Well, one has to start. :) – TobiMcNamobi Sep 02 '14 at 11:54
  • "Should" implies a necessity, some compelling external reason why it "ought to" be called this. «The Naming Of Things is a difficult thing. It isn't just one of your holiday games» (T.S. Elliott?) _(Also, naming things was a prime responsibility given to mankind in some dominant religions_ ... :) wink wink) – sehe Sep 02 '14 at 11:58
  • Thanks for the suggestions. I think "lambda chain" come closest to "function composition" used in Haskell. "Curry sausage" would have been funny if currying was actually done (instead currying is needed when using functions with more than 1 parameter). – stefaanv Sep 02 '14 at 13:33
  • If we're going this route, I suggest _The Forbidden Dance is Lambda_. – Spire Sep 12 '14 at 20:27