66

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.

Jonas
  • 6,915
  • 8
  • 35
  • 53
Gigaxel
  • 1,058
  • 1
  • 9
  • 20
  • 38
    May I ask why exactly you're trying to do functional programming in c++ (as opposed to any inherently functional language)? – Ben Steffan May 04 '17 at 12:58
  • 12
    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 May 04 '17 at 12:58
  • 2
    @BenSteffan I have been practicing C++ lately and I want to get as deep as possible into the language and its libraries, and I wanted to try out the functional library. I have implemented the f(a)(b) function easily, but I cannot figure out how to implement f(a)(b)(c), and I do not want to go further until I figured it out xD – Gigaxel May 04 '17 at 13:01
  • 1
    @NathanOliver I think I would know how to implement f(a)(b)(c)(), but I want to make it work for f(a)(b)(c) :( – Gigaxel May 04 '17 at 13:05
  • 6
    @BenSteffan C++ offered function objects before some of the mainstream functional languages came about. Iterators and algorithms are just one feature that was transferred from C++ to functional languages. It *already* supports lambdas. It *already* allows passing functions as arguments to iterators. etc etc etc – Panagiotis Kanavos May 04 '17 at 13:06
  • 1
    @Gigaxel Can you explain what have you done, i.e. what does `[a]`? – am.rez May 04 '17 at 13:17
  • 7
    @am.rez that's the [lambda-expression's capture list](http://en.cppreference.com/w/cpp/language/lambda). – Quentin May 04 '17 at 13:18
  • 6
    @am.rez It allows the lambda function to use the parameter of the plus2 function in its body. – Gigaxel May 04 '17 at 13:18
  • 9
    Note that you can use `auto` for the return type of your function, and avoid the type erasure cost of `std::function`. – Quentin May 04 '17 at 13:23
  • 1
    @Quentin Yes, I am aware of it, but I wanted to make it clearer what the return type is. I could have solved the problem If I used auto for the return type, because I was implementing the function correctly, but the return type was not correct. Thank you for the extra tips :D – Gigaxel May 04 '17 at 13:28
  • 2
    Personally I think the best way to understand the functional aspects of C++ is to first learn a functional language and then come back to C++ because it gives you more of an insight into the classless world lambda expressions came from. – Pharap May 05 '17 at 11:13
  • 1
    @Pharap I agree. I think the point of learning a functional language is to learn thinking computation differently. Personally, I love Scheme because it is easy to learn and it awards you when you do it in a functional way (cleaner code). Of course, Haskell (and ML) is also very good (and popular) but I find it slightly harder and I am still learning it. – Alex Vong May 05 '17 at 12:51
  • 4
    OP - Is the goal to *fold* some binary function `f` or to *curry* some arbitrary-arity function `f`? – Barry May 05 '17 at 13:53
  • 2
    @AlexVong I chose to learn Haskell as my first functional language because there's a very nice tutorial for it called '[Learn You A Haskell For Great Good](http://learnyouahaskell.com/chapters)'. It's not enough for mastering the language, but it's a good starting point that makes the learning curve less steep. – Pharap May 06 '17 at 12:07
  • 1
    @Pharap Thanks for sharing the resource. I am definitely going to check out Haskell in the near feature :D – Gigaxel May 06 '17 at 12:10
  • 1
    @Pharap Can confirm that the book is amazing for a beginner, and what's even more amazing is that at the time of its writing the author was a student (in Slovenia)! – vsoftco May 06 '17 at 23:04
  • 1
    @BenSteffan: OP clearly wants to improve their knowledge of C++ by attempting this exercise. That's a great idea! – Tom Swirly May 07 '17 at 14:57
  • @TomSwirly I dind't mean to criticise OP, it just struck me as an odd idea, hence I asked. – Ben Steffan May 07 '17 at 17:42
  • @BenSteffan It's not odd if you look at it from a beginner's perspective. Sometimes the best way to learn how something works is to abuse it until it is broken, after which it will become aparent why it is a bad idea and why people do not do it. – Pharap May 07 '17 at 18:25

9 Answers9

115

You can do it by having your function f return a functor, i.e., 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() const { 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() const { 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;
Jonas
  • 6,915
  • 8
  • 35
  • 53
  • 4
    The whole point of lambdas and `std::function` is that you *don't* need to create a class just to implement `()`. You can create actual functions and pass them around. Using function objects isn't considered good C++ practice. I didn't downvote but *this* class would cause problems if you tried to use it for iteration or any other STL method that expects a lambda – Panagiotis Kanavos May 04 '17 at 13:08
  • 1
    @Jonas I agree with Panagiotis. I wanted to implement my function with lambdas and std::function. I didn't down vote your answer as well even though it wasn't the answer I was looking for :/ – Gigaxel May 04 '17 at 13:11
  • 1
    I did not downvote but look at [wikipedia](https://en.wikipedia.org/wiki/Functional_programming). "In functional code, the output value of a function depends only on the arguments that are passed to the function, so calling a function f twice with the same value for an argument x will produce the same result f(x) each time; this is in contrast to procedures depending on local or global state" – Logman May 04 '17 at 13:11
  • 46
    @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 May 04 '17 at 13:11
  • 10
    @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 May 04 '17 at 13:14
  • 16
    @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 May 04 '17 at 13:18
  • 6
    Note that the whole class here can be local to the function, too. So no worries of polluting the global namespace. – Quentin May 04 '17 at 13:19
  • 6
    @Gigaxel it is the better answer than you choose as the answer eevn if you do not like it – Slava May 04 '17 at 13:38
  • @Jonas you may change this class to template and make binary operator as a template argument. Would be even better – Slava May 04 '17 at 13:39
  • 1
    @Slava It wasn't the answer I was looking for :/ – Gigaxel May 04 '17 at 13:41
  • 7
    @Gigaxel answer that you like is not practical, you do not want to manually write all combinations of lambdas for chain invocation. – Slava May 04 '17 at 13:43
  • @Jonas type of expression should also be a template parameter. Otherwise you would need a special class that change it's type based on arguments applied to it. – Slava May 04 '17 at 13:45
  • @Slava the answer he accepted answered the specified question; this suggest a good solution to his problem *but not in the form he asked* - that was explicitly mentioned. answers that do cool stuff shortly are cool - but sometimes they are not really answering the question fully. – Uriel May 04 '17 at 13:46
  • 26
    @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 May 04 '17 at 14:11
  • @JerryCoffin just like all functional languages that run over JVM or the .NET runtime. It's not what's generated that makes a language or style functioal, it's how it's used. When talking about *functional* programming, one looks for ways to define a *function*, not a class that acts like a function – Panagiotis Kanavos May 04 '17 at 15:02
  • 14
    @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 May 04 '17 at 15:10
  • 15
    @PanagiotisKanavos: By that argument, you've excluded lambdas, which are also classes that act like functions, and not actual functions. – Mooing Duck May 04 '17 at 16:43
  • @MooingDuck congrats. You win. I remember trying to explain to an old professor back in 1993 why object orientation wasn't plain old C. He insisted was that since C++ was converted to C, there was no difference between OO and plain-old C – Panagiotis Kanavos May 05 '17 at 06:57
  • 8
    @PanagiotisKanavos Damn... By that logic there is no difference any programming languages, they are all "converted" to binary code :-/ – Jonas May 05 '17 at 07:00
  • 7
    @PanagiotisKanavos: Most plain-old C libraries/objects _are_ OO. The same concepts apply. Not all C, but most large C objects. You have some data with the internal vars, a constructor function, some "method" functions, and a destructor function. Composition is trivial. inheritance is nontrivial, but still easily doable. `shape* s = makeSquare(3); int area = s->area(s); s->freeShape(s);` – Mooing Duck May 05 '17 at 16:40
  • Clever and neat - in some ways the best solution to that sort of problem as it works for any number of arguments. But it isn't really a _functional_ solution. More, it doesn't _actually_ return `a + b + c` but rather "an object which autoconverts to `a + b + c` on request" which isn't really the same thing... – Tom Swirly May 07 '17 at 14:55
  • 2
    @TomSwirly: In a functional context, those are the same thing – Mooing Duck May 07 '17 at 19:19
  • 1
    @PanagiotisKanavos: The full class definition is necessary because of the implicit cast back to the value type, not because of `operator()`. Without a class def, there's no way to get the answer out. More generally, to allow both `f(a)(b)` and `f(a)(b)(c)(d)` to return values, you'll need SOME way of converting a `sum` (or whatever) to a `double`. – leewz May 08 '17 at 12:00
  • @MooingDuck: In C++, those are decidedly not the same thing. And this is not in fact a "functional" solution. – Tom Swirly May 09 '17 at 11:18
60

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;
                };
            };
        };
    }
    
Uriel
  • 15,579
  • 6
  • 25
  • 46
  • 11
    Nice, gets what the OP wants, but it doesn't expand well. – NathanOliver May 04 '17 at 13:23
  • 4
    That is exactly how I was trying to implement it but I did not include std::function(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 May 04 '17 at 13:24
  • 3
    Nice, is it possible to generalize to, e.g., fewer and more elements? – Jonas May 04 '17 at 13:28
  • 1
    @Jonas OP has also demonstrated for 2, and yes, you can expand with more nested lambdas. – Uriel May 04 '17 at 13:30
  • 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 May 04 '17 at 13:33
  • @Ðаn I'm not sure about this one; this would work the same as `plus2(plus2(a, b), c)`, but it wouldn't be the same, since in this case we return a *function* that would later pair with `b` and `c`, we don't have them all in advance. – Uriel May 04 '17 at 13:34
  • @Ðаn I'm not sure. I do not think so as is but you might be able to tweak it. Personally I prefer Jonas solution as it scales automatically and requires no TMP. – NathanOliver May 04 '17 at 13:37
  • @Ðаn yea, that would be right. seems to me that although not explicitly written, OP is asking for currying syntax actually (lambda that returns lambda) rather than functional programming in general – Uriel May 04 '17 at 13:42
  • 8
    @Jonas: The usual solution to that would be non-type template parameters, specifically defining `plus` in terms of `plus`. The downside is obvious; you'd still need to specify the exact number of arguments up front. – MSalters May 04 '17 at 15:05
  • So if I wanted `plus5`, I need to write everything from scratch again, even though everything is repeated? And if I wanted `times5`, I need to reduplicate everything again? This is a hyper-specific solution to a toy problem. -1. – Barry May 05 '17 at 13:58
  • @Barry that's what you get for a functional approach; of course you can reuse plus2 (as some of the latest answers do), but I build my answer believing op tried to understand how to design the function for a specific case. and for the same reason I used the way I did and didn't use templates - not because it is better in practice, but because it answers the main issue discussed here which is lambdas usage. – Uriel May 05 '17 at 14:48
  • Also, do note that the second solution doesn't work in C++11 or 14. – Tom Swirly May 07 '17 at 14:51
  • @Barry: The asker wants currying, and is presumably asking the question to improve their understanding of Haskell. Haskell doesn't have n-ary currying. This answer corresponds better to the Haskell concept. @ Uriel, IMO, currying is independent of functional. – leewz May 08 '17 at 11:52
  • @leewz This answer doesn't really correspond to Haskell. I can't call `plus4(1,2,3,4)` if I wanted to. Moreover, if I wanted a different operation, I'd have to rewrite everything from scratch. If you want a more Haskell-style currying, see my answer. – Barry May 08 '17 at 13:10
30

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

vsoftco
  • 55,410
  • 12
  • 139
  • 252
  • 4
    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 May 04 '17 at 16:27
  • Pardon my ignorance, but how does the compiler know to call your cast operator? I see that it couldn't really do anything else, since there's no insertion operator defined, but I didn't realise that something like this would work without being explicit with the cast. – Dave Branton May 07 '17 at 21:14
  • 1
    @DaveBranton The rules of the language say that the compiler is allowed to try at most one user-defined conversion. In our case, we have such a conversion operator, so in `cout << s(1)(2)(3)` the compiler first sees that it cannot simply display it, then it searches for user-defined conversion operators, and finds `Sum::operator T() const`. It then applies the conversion to `T` then displays the `T` if it can (in our case it can because it is an `int`). – vsoftco May 07 '17 at 21:36
  • This is how function chaining is implemented. – KeyC0de Sep 27 '18 at 16:07
15

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([=](auto... new_args)
                    -> decltype(std::invoke(f, args..., new_args...))
                {
                    return std::invoke(f, args..., new_args...);
                });
        }
    };  
}

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
Barry
  • 286,269
  • 29
  • 621
  • 977
  • 4
    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 - Adam Nevraumont May 05 '17 at 14:13
  • @Yakk Hoping to make it [even tidier](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0573r0.html)! Need to find time to revise that paper... – Barry May 05 '17 at 14:37
  • 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 - Adam Nevraumont May 05 '17 at 14:41
  • @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 May 05 '17 at 14:43
12

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.

  • 2
    This is great! It scales neatly, and the implementation is nice and simple. – Jonas May 04 '17 at 16:43
  • @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 - Reinstate Monica May 04 '17 at 17:49
  • 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 - Reinstate Monica May 04 '17 at 17:49
11

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.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • This is cool! And I think it can be used as replacement for `std::bind` in some cases :) – Slava May 05 '17 at 13:37
  • Interesting. You wrote fold and I wrote curry. Wonder what OP actually wants. – Barry May 05 '17 at 13:59
  • 1
    @Barry Obviously "an ad-hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp" – Yakk - Adam Nevraumont May 05 '17 at 14:15
  • @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 - Adam Nevraumont May 05 '17 at 19:58
  • 1
    @Yakk TBH I'm mostly just baffled at how many upvotes some of these top answers have. – Barry May 05 '17 at 20:05
  • 1
    @Barry It was linked in the sidebar. /shrug. – Yakk - Adam Nevraumont May 05 '17 at 20:26
10

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
}
Justin
  • 24,288
  • 12
  • 92
  • 142
4

All these answers seem terribly complicated.

auto f = [] (double a) {
    return [=] (double b) {
        return [=] (double c) {
            return a + b + c;
        };
    };
};

does exactly what you want, and it works in C++11, unlike many or perhaps most other answers here.

Note that it does not use std::function which incurs a performance penalty, and indeed, it can likely be inlined in many cases.

Tom Swirly
  • 2,740
  • 1
  • 28
  • 44
-8

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;
}
mathreadler
  • 447
  • 5
  • 16
  • 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 May 05 '17 at 02:35
  • 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 May 05 '17 at 06:35
  • 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 May 05 '17 at 06:41
  • @JDługosz: The purpose is the same as for the singleton design pattern, (as is mentioned in the first line of the answer): to avoid to have many instances of the class for something which should not have more than one. I agree the assignment instead of initialization is unnecessary, but should not make any difference for a good compiler, should it? – mathreadler May 05 '17 at 08:37
  • @JDługosz: fixed the unnecessary assignment. – mathreadler May 05 '17 at 09:01
  • 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 [codereview.se] so you can learn what's so horrifying about it. – JDługosz May 05 '17 at 09:30
  • The use of `mInstance` makes this thread-unsafe and I guess you wouldn't even be able to use it several times on the same thread correctly. This is supposed to be a _pure_ operation with nothing but local data. Also the formatting is horribly sloppy. – DarkDust May 05 '17 at 11:34
  • It works great on my one-thread unit tests. There are several ways to make it thread safe but thread safety was not mentioned in the question so dealing with it was also not mentioned in the answer. – mathreadler May 05 '17 at 11:47
  • 1
    The code doesn't even compile (missing a colon and semicolon). Once you fix that and make the constructor public, you can completely eliminate `mInstance` and the `add` method and simply do `adder(1.0)(2.0)(1.0);`. This pattern of yours, that you say we would use if we "learned some object oriented design patterns" is completely useless. – DarkDust May 05 '17 at 12:22
  • 5
    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 - Adam Nevraumont May 05 '17 at 12:55