Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is this C++14 construct called which seems to chain lambdas?

Tags:

c++

lambda

c++14

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.

like image 986
stefaanv Avatar asked Sep 02 '14 09:09

stefaanv


People also ask

What is the type of lambda expression C++?

The type of a lambda expression is unspecified. But they are generally mere syntactic sugar for functors. A lambda is translated directly into a functor.

How do you call a lambda function in C++?

A lambda is also just a function object, so you need to have a () to call it, there is no way around it (except of course some function that invokes the lambda like std::invoke ). If you want you can drop the () after the capture list, because your lambda doesn't take any parameters.

Why do we need lambda expressions in C++?

One of the new features introduced in Modern C++ starting from C++11 is Lambda Expression. It is a convenient way to define an anonymous function object or functor. It is convenient because we can define it locally where we want to call it or pass it to a function as an argument.

Do lambdas exist in C?

No, C doesn't have lambda expressions (or any other way to create closures). This is likely so because C is a low-level language that avoids features that might have bad performance and/or make the language or run-time system more complex.

What is lambda expression in C++?

Last Updated : 21 Jun, 2018 C++ 11 introduced lambda expression to allow us write an inline function which can be used for short snippets of code that are not going to be reuse and not worth naming. In its simplest form lambda expression can be defined as follows: [ capture clause ] (parameters) -> return-type { definition of method }

What is constructor chaining?

This is often referred to as constructor chaining in the C# world. This guide will teach you how to utilize this technique, show you how to use it to your own advantage, and give you some tricks that allow you to expand on the idea and find your own solutions.

How do lambda expressions have more power than ordinary functions?

A lambda expression can have more power than an ordinary function by having access to variables from the enclosing scope. We can capture external variables from enclosing scope by three ways :

What is the Order of the call to a constructor?

The order of the call is as follows: First, we call the constructor which is referenced with the :this () keyword, and if that also references another constructor, it will also call that constructor, climbing up the call chain. Let's build a fully fledged example to climb the chain.


2 Answers

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

  • In Haskell this would written as world . hello $ stdout and is called function composition.
  • In clojure it would be (-> stdout hello world) and is called the "thread-first" macro

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

like image 176
stefaanv Avatar answered Oct 18 '22 01:10

stefaanv


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.

like image 30
Yakk - Adam Nevraumont Avatar answered Oct 18 '22 02:10

Yakk - Adam Nevraumont