I have been getting into the basics of functional programming with C++. I am trying to make a function f(a)(b)(c) that will return a + b + c. I successfully implemented the function f(a)(b) which returns a + b. Here is the code for it:

std::function<double(double)> plus2(double a){
    return[a](double b){return a + b; };
}

I just cannot figure out how to implement the function f(a)(b)(c) which as I previously stated should return a + b + c.

share|improve this question
29  
May I ask why exactly you're trying to do functional programming in c++ (as opposed to any inherently functional language)? – Ben Steffan yesterday
10  
Not sure if you can do it with just f(a)(b)(c). You should be able to get it working fairly easily if you want to use f(a)(b)(c)(). – NathanOliver yesterday
7  
@am.rez that's the lambda-expression's capture list. – Quentin yesterday
6  
@am.rez It allows the lambda function to use the parameter of the plus2 function in its body. – Gigaxel yesterday
9  
Note that you can use auto for the return type of your function, and avoid the type erasure cost of std::function. – Quentin yesterday
up vote 36 down vote accepted

Just take your 2 elements solution and expand it, by wrapping it with another lambda.

Since you want to return a lambda that get a double and returns a doubles' addition lambda, all you need to do is to wrap your current return type with another function, and add a nested lambda into your current one (a lambda that returns a lambda):

std::function<std::function<double(double)>(double)> plus3 (double a){
    return [a] (double b) {
        return [a, b] (double c) {
            return a + b + c;
        };
    };
}

  • As @Ðаn noted, you can skip the std::function<std::function<double(double)>(double)> and get along with auto:

    auto plus3 (double a){
        return [a] (double b) {
            return [a, b] (double c) { return a + b + c; };
        };
    }
    
  • You can expand this structure for every number of elements, using deeper nested lambdas. Demonstration for 4 elements:

    auto plus4 (double a){
        return [a] (double b) {
            return [a, b] (double c) {
                return [a, b, c] (double d) {
                    return a + b + c + d;
                };
            };
        };
    }
    
share|improve this answer
9  
Nice, gets what the OP wants, but it doesn't expand well. – NathanOliver yesterday
2  
That is exactly how I was trying to implement it but I did not include std::function<double(double)>(double). Thank you, it made a lot of things clearer and now I now how to nest it even deeper(even though I don't want to go further than that). – Gigaxel yesterday
3  
Nice, is it possible to generalize to, e.g., fewer and more elements? – Jonas yesterday
3  
@Uriel I'm aware of the possibility of nesting more lambdas. How would you go about implementing it without defining a new function like plus2 and plus4? – Jonas yesterday
6  
@Jonas: The usual solution to that would be non-type template parameters, specifically defining plus<N> in terms of plus<N-1>. The downside is obvious; you'd still need to specify the exact number of arguments up front. – MSalters yesterday

You can do it by having f return an object that implements operator(). Here is one way to do it:

struct sum 
{
    double val;

    sum(double a) : val(a) {}

    sum operator()(double a) { return val + a; }

    operator double() { return val; }
};

sum f(double a)
{
    return a;
}

Example

Link

int main()
{
    std::cout << f(1)(2)(3)(4) << std::endl;
}

Template version

You can even write a templated version that will let the compiler deduce the type. Try it here.

template <class T>
struct sum 
{
    T val;

    sum(T a) : val(a) {}

    template <class T2>
    auto operator()(T2 a) -> sum<decltype(val + a)> { return val + a; }

    operator T() { return val; }
};

template <class T>
sum<T> f(T a)
{
    return a;
}

Example

In this example, T will ultimately resolve to double:

std::cout << f(1)(2.5)(3.1f)(4) << std::endl;
share|improve this answer
32  
@PanagiotisKanavos what are you on about... Standard algorithms expect functions or function objects. A lambda-expression is syntactic sugar for a function object. There won't be any problem because it is exactly the same thing, and is even defined as such in the standard. Also, std::function is tangent to the discussion -- that's for type erasure. – Quentin yesterday
7  
@Logman: As you can see,the state of evaluation of sum(a)(b)(c) is captured fully within each sum. There is neither local nor global state. – MSalters yesterday
9  
@PanagiotisKanavos: The problem with lambda's is that they're anonymous. But as you see here, sum::operator() returns sum. Lacking a name, that kind of self-reference is impossible for lambda's. – MSalters yesterday
14  
@PanagiotisKanavos: First and foremost, you should realize that in C++, a lambda expression is just an alternative syntax to define a class that overloads operator(). There's not a thing in the world wrong with using the "normal" syntax to create such a class (especially for cases where the lambda expression syntax doesn't work so well). – Jerry Coffin yesterday
8  
@PanagiotisKanavos: Note that different languages have different definitions of exactly what constitutes a function. C++ already inherited a definition of function from C, so it needed a new term for the broader concept. A nominal difference doesn't mean callable objects in C++ are structurally different from functions in functional languages. If it walks like a duck and talks like a duck, it is a duck. – MSalters yesterday

Here is a slightly different approach, which returns a reference to *this from operator(), so you don't have any copies floating around. It is a very simple implementation of a functor which stores state and left-folds recursively on itself:

#include <iostream>

template<typename T>
class Sum
{
    T x_{};
public:
    Sum& operator()(T x)
    {
        x_ += x;
        return *this;
    }
    operator T() const
    {
        return x_;
    }
};

int main()
{
    Sum<int> s;
    std::cout << s(1)(2)(3);
}

Live on Coliru

share|improve this answer
3  
this works for any number of (summand) and is recursive, i.e. does not require to define yet another function/lambda for each level. – Walter yesterday

The simplest way I can think of to do this is to define plus3() in terms of plus2().

std::function<double(double)> plus2(double a){
    return[a](double b){return a + b; };
}

auto plus3(double a) {
    return [a](double b){ return plus2(a + b); };
}

This combines the first two argument lists into a single arglist, which is used to call plus2(). Doing so allows us to reuse our pre-existing code with minimal repetition, and can easily be extended in the future; plusN() just needs to return a lambda that calls plusN-1(), which will pass the call down to the previous function in turn, until it reaches plus2(). It can be used like so:

int main() {
    std::cout << plus2(1)(2)    << ' '
              << plus3(1)(2)(3) << '\n';
}
// Output: 3 6

Considering that we're just calling down in line, we can easily turn this into a function template, which eliminates the need to create versions for additional arguments.

template<int N>
auto plus(double a);

template<int N>
auto plus(double a) {
    return [a](double b){ return plus<N - 1>(a + b); };
}

template<>
auto plus<1>(double a) {
    return a;
}

int main() {
    std::cout << plus<2>(1)(2)          << ' '
              << plus<3>(1)(2)(3)       << ' '
              << plus<4>(1)(2)(3)(4)    << ' '
              << plus<5>(1)(2)(3)(4)(5) << '\n';
}
// Output: 3 6 10 15

See both in action here.

share|improve this answer
1  
This is great! It scales neatly, and the implementation is nice and simple. – Jonas yesterday
    
@Jonas Thanks. When you're trying to expand an existing framework like this, the simplest way is probably to find a way to define the expanded version in terms of the current version, unless that would be too convoluted. I also don't believe the prototype is strictly necessary for the templated version, but it can increase clarity in some cases. – Justin Time yesterday
    
It does have the flaw of being executed at runtime, though, but that can be mitigated once more compilers properly support constexpr lambdas. – Justin Time yesterday

If you are open to using libraries, this is really easy in Boost's Hana:

double plus4_impl(double a, double b, double c, double d) {
    return a + b + c + d;
}

constexpr auto plus4 = boost::hana::curry<4>(plus4_impl);

And then using it is just as you desire:

int main() {
    std::cout << plus4(1)(1.0)(3)(4.3f) << '\n';
    std::cout << plus4(1, 1.0)(3)(4.3f) << '\n'; // you can also do up to 4 args at a time
}
share|improve this answer

I'm going to play.

You want to do a curried fold over addition. We could solve this one problem, or we could solve a class of problems that include this.

So, first, addition:

auto add = [](auto lhs, auto rhs){ return std::move(lhs)+std::move(rhs); };

That expresses the concept of addition pretty well.

Now, folding:

template<class F, class T>
struct folder_t {
  F f;
  T t;
  folder_t( F fin, T tin ):
    f(std::move(fin)),
    t(std::move(tin))
  {}
  template<class Lhs, class Rhs>
  folder_t( F fin, Lhs&&lhs, Rhs&&rhs):
    f(std::move(fin)),
    t(
      f(std::forward<Lhs>(lhs), std::forward<Rhs>(rhs))
    )
  {}
  template<class U>
  folder_t<F, std::result_of_t<F&(T, U)>> operator()( U&& u )&&{
    return {std::move(f), std::move(t), std::forward<U>(u)};
  }
  template<class U>
  folder_t<F, std::result_of_t<F&(T const&, U)>> operator()( U&& u )const&{
    return {f, t, std::forward<U>(u)};
  }
  operator T()&&{
    return std::move(t);
  }
  operator T() const&{
    return t;
  }
};

It takes a seed value and a T, then permits chaining.

template<class F, class T>
folder_t<F, T> folder( F fin, T tin ) {
  return {std::move(fin), std::move(tin)};
}

Now we connect them.

auto adder = folder(add, 0);
std::cout << adder(2)(3)(4) << "\n";

We can also use folder for other operations:

auto append = [](auto vec, auto element){
  vec.push_back(std::move(element));
  return vec;
};

Use:

auto appender = folder(append, std::vector<int>{});
for (int x : appender(1)(2)(3).get())
    std::cout << x << "\n";

Live example.

We have to call .get() here because for(:) loops doesn't understand our folder's operator T(). We can fix that with a bit of work, but .get() is easier.

share|improve this answer
    
This is cool! And I think it can be used as replacement for std::bind in some cases :) – Slava 10 hours ago
    
Interesting. You wrote fold and I wrote curry. Wonder what OP actually wants. – Barry 10 hours ago
1  
@Barry Obviously "an ad-hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp" – Yakk 9 hours ago
    
@Barry Actually, my design (that it doesn't terminate) is a problem. The operator T is a hack. If I mix curry with folding, we can provide a binary operation and an argument size to generate a curried fold over +. That lets us do auto f = fold<4>(add);, which might match what the OP wants better than either of our answers. – Yakk 4 hours ago
    
@Yakk TBH I'm mostly just baffled at how many upvotes some of these top answers have. – Barry 4 hours ago

This isn't f(a)(b)(c) but rather curry(f)(a)(b)(c). We wrap f such that each additional argument either returns another curry or actually invokes the function eagerly. This is C++17, but can be implemented in C++11 with a bunch of extra work.

Note that this is a solution for currying a function - which is the impression that I got from the question - and not a solution for folding over a binary function.

template <class F>
auto curry(F f) {
    return [f](auto... args) -> decltype(auto) {
        if constexpr(std::is_invocable<F&, decltype(args)...>{}) {
            return std::invoke(f, args...);
        }
        else {
            return curry(
                [f, tup=std::make_tuple(args...)](auto... new_args)
                    -> decltype(std::invoke(f, args..., new_args...))
                {
                    return std::apply([&](auto... args) -> decltype(auto){
                        return std::invoke(f, args..., new_args...);
                    }, tup);
                });
        }
    };
}

I've skipped forwarding references for brevity. Example usage would be:

int add(int a, int b, int c) { return a+b+c; }

curry(add)(1,2,2);       // 5
curry(add)(1)(2)(2);     // also 5
curry(add)(1, 2)(2);     // still the 5th
curry(add)()()(1,2,2);   // FIVE

auto f = curry(add)(1,2);
f(2);                    // i plead the 5th
share|improve this answer
    
C++17 makes that so tidy. Writing my function curry in C++14 was much more painful. Note that for full efficiency, you may need a function object that conditionally moves its tuple of state depending on invocation context. That may require decoupling tup and maybe f from the lambda capture list so it can be passed in with different rvalueness depending on how () is called. Such a solution goes beyond the scope of this question, however. – Yakk 10 hours ago
    
@Yakk Hoping to make it even tidier! Need to find time to revise that paper... – Barry 9 hours ago
    
I don't see anything in there that permits perfect forwarding of the "this" of the lambda itself, so if invoked in a maybe-rvalue context you can forward by-value captured things perfectly. That may have to be a different proposal. (Aside: how would you distinguish between the lambda's *this context and the enclosing method's *this context? Hurm.) – Yakk 9 hours ago
    
@Yakk Nope, I'm just trying to make simple lambdas shorter. There was something floating around std-proposals of doing something like auto fact = [] self (int i) { return (i < = 1) ? 1 : i * self(i-1); }; but I can't find a paper. – Barry 9 hours ago

Here is a state pattern singleton inspired approach using operator() to change state.

Edit: Exchanged the unnecessary assignment for an initialization.

#include<iostream>
class adder{
private:
  adder(double a)val(a){}
  double val = 0.0;
  static adder* mInstance;
public:
  adder operator()(double a){
    val += a;
    return *this;}
  static adder add(double a){
    if(mInstance) delete mInstance;
    mInstance = new adder(a);
    return *mInstance;}
  double get(){return val;}
};
adder* adder::mInstance = 0;
int main(){
  adder a = adder::add(1.0)(2.0)(1.0);
  std::cout<<a.get()<<std::endl;
  std::cout<<adder::add(1.0)(2.0)(3.0).get()<<std::endl;
  return 0;
}
share|improve this answer
3  
I'm not one of the downvoters, but it is probably because the code is poorly formatted, it is as far from a zero cost abstraction as possible (that is, compared to other, cleaner, C++ solutions, it is extremely slow and painful to look at), and the OP implied that he wanted a FP style solution, whereas this is about as far from FP as possible. – rationalcoder 21 hours ago
    
Your constructor assigns to the member (rather than initializes) but you also have implicit initialization specified on the val member, so that's unnecessary. – JDługosz 17 hours ago
    
I don’t see the point of the static add function. What ever is the point of storing a pointer to the instance in an internal member? You appear to have no problem returning values too. – JDługosz 17 hours ago
1  
The :val(0) is still unnecessary. The use of mInstance is so rediculus that it overshadows everything else. Based on the initial comment, you should post a question on Code Review so you can learn what's so horrifying about it. – JDługosz 14 hours ago
1  
Oh my god, that is horrible. In any case, remove mInstance, replace add's entire body with return {a};, and your code becomes less ridiculously wasteful. That heap allocation and static state does nothing. Still doesn't solve OP's problm, as OP doesn't want the .get(), but it at least wouldn't be horrible. – Yakk 11 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.