54

Can someone guide me how do functional programming in C++? Is there some good online material that I can refer?

Please note that I know about the library FC++. I want to know how to do that with C++ standard library alone.

Thanks.

Red Hyena
  • 2,988
  • 5
  • 25
  • 24
  • 20
    You are better off using a functional programming language (LISP, Haskell, Scheme, ...). That way you are sure what you are doing is indeed functional programming. – Brian R. Bondy Dec 30 '09 at 17:40
  • 4
    What kind of FP-features are you looking for? Boost provides some FP-like libraries (mpl, function, lambda, etc) and some of these will be in C++0x and are in TR1 already. – Macke Dec 30 '09 at 17:48
  • @Brian : I just wanna get feel of FP without learning a new language. And right now I know only C++ and Java. And Java I guess would be even worse option for FP. – Red Hyena Dec 30 '09 at 18:04
  • 1
    @Marcus : All basic stuff. I just wanna get feel of FP. I just wanna know what is there in FP that's attracting so many people towards it these days. – Red Hyena Dec 30 '09 at 18:07
  • 10
    @Jacob: You will probably not learn that by "trying" it in C++. It's like saying, "I want to learn what's so neat about Object-Oriented Programming. How do I do OOP in VAX assembly?" – Chuck Dec 30 '09 at 18:25
  • @Chuck : So what do you suggest I should do? – Red Hyena Dec 30 '09 at 18:33
  • @Jacob... I agree with Chuck. Just learn a new language. The functional programming style and constraints will show themselves as you learn. My suggestion is to do an impure functional language, like F#, OCAML, Scala, Closure. – nlucaroni Dec 30 '09 at 18:43
  • 4
    @Jacob: I'd suggest you learn OCaml or F#. For most people, wrapping your head around functional programming is the hard part. Learning a language that helps you do this will make it less work, not more. – Chuck Dec 30 '09 at 18:46
  • Okay. I'll check out some FP language. Thanks for the responses! – Red Hyena Dec 30 '09 at 18:51
  • 7
    While I agree with Chuck in general, I have to disagree with the specific language suggestions. If you want to learn functionaæl programming, pick a language that is designed *specifically* for functional programming. OCaml and F# are hybrid languages with a lot of OOP features. That means someone familiar with OOP will be tempted to try to stay within the familiar OOP style. I'd jump into something like SML or Haskell instead, where you're forced to use FP and nothing else. – jalf Dec 30 '09 at 19:43
  • 2
    Read "Structure and Interpretation of Computer Programs": http://mitpress.mit.edu/sicp/full-text/book/book.html – Thomas Eding Jan 04 '10 at 07:29
  • 1
    For what it's worth, you may be interested in [John Carmack's thoughts on functional programming in C++](http://www.altdevblogaday.com/2012/04/26/functional-programming-in-c/). – Chris Frederick Sep 10 '12 at 03:28

6 Answers6

49

You can accomplish a surprising amount of "functional programming" style with modern C++. In fact, the language has been trending in that direction since its' standardization.

The standard library contains algorithms analogous to map, reduce, etc (for_each, transform, adjacent_sum...). The next revision, C++0x, contains many features designed to let programmers work with these in a more functional style (lambda expressions, etc.).

Look into the various Boost libraries for more fun. Just to illustrate that standard C++ contains plenty of functional goodness, here's a factorial function in continuation-passing style in standard C++.

#include <iostream>

// abstract base class for a continuation functor
struct continuation {
    virtual void operator() (unsigned) const = 0;
};

// accumulating continuation functor
struct accum_cont: public continuation {
    private:
        unsigned accumulator_;
        const continuation &enclosing_;
    public:
        accum_cont(unsigned accumulator, const continuation &enclosing)
            : accumulator_(accumulator), enclosing_(enclosing) {}; 
        virtual void operator() (unsigned n) const {
            enclosing_(accumulator_ * n);
        };
};

void fact_cps (unsigned n, const continuation &c)
{
    if (n == 0)
        c(1);
    else
        fact_cps(n - 1, accum_cont(n, c));
}

int main ()
{
    // continuation which displays its' argument when called
    struct disp_cont: public continuation {
        virtual void operator() (unsigned n) const {
            std::cout << n << std::endl;
        };
    } dc;

    // continuation which multiplies its' argument by 2
    // and displays it when called
    struct mult_cont: public continuation {
        virtual void operator() (unsigned n) const {
            std::cout << n * 2 << std::endl;
        };
    } mc;

    fact_cps(4, dc); // prints 24
    fact_cps(5, mc); // prints 240

    return 0;
}

Ok, I lied a little bit. It's a factorial functor. After all, closures are a poor man's objects... and vice versa. Most of the functional techniques used in C++ rely on the use of functors (i.e. function objects)---you'll see this extensively in the STL.

Derrick Turk
  • 4,246
  • 1
  • 27
  • 27
  • 1
    Nice example. But the choice of identifier names I must say is very bad, So if you could please edit your post and use some better identifier names. I have upvoted you by the way. Thanks! :) – Red Hyena Dec 30 '09 at 18:54
  • 2
    "After all, closures are a poor man's objects... and vice versa." i have to disagree. yes, you can implement one using the other... but what happens if you want to reimplement objects based on functors? a hideous mess. and if you reimplement closures on top of closure-based objects? it unravels itself (almost) to the 'native' concepts. Thus, i think closures are _far_ more appropriate as 'primitives' than objects (and don't get me started about class-based objects!) – Javier Dec 30 '09 at 19:40
  • Thanks, Jacob! I cleaned up the example a little bit. It was never intended for public display; I had just read Lambda: The Ultimate Imperative one day and wanted to try CPS in C++. But then I saw this question and just had to share... – Derrick Turk Dec 30 '09 at 20:28
  • 1
    @Javier: I know it's one of those equivalences that's not necessarily very important in practice (cf. Turing-equivalence). However, standard C++ is actually heading toward making "closures" more transparent (with objects, as far as I know, under the hood. Even with the current language functors are widely used to fulfill the same purposes as "first-class" closures. – Derrick Turk Dec 30 '09 at 20:31
  • What I miss in C++ as a functional language is an easy notation for currying and function composition, tail-call optimization, closures that do not become invalid as soon as their captured variables go out of scope, ... – Giorgio Sep 27 '12 at 17:28
  • I'm surprised no one mentioned C++03+TR1 or C++11's `std::function`, `std::bind`, and `std::ref`. Together you get "functions as arguments". That with `#include `, and crafting functions without side-effects, you can do functional programming. – Charles L Wilcox Mar 28 '13 at 20:38
26

Update August 2014: This answer was posted in 2009. C++11 improved matters considerably for functional programming in C++, so this answer is no longer accurate. I'm leaving it below for a historical record.

Since this answer stuck as the accepted one - I'm turning it into a community Wiki. Feel free to collaboratively improve it to add real tips on function programming with modern C++.


You can not do true functional programming with C++. All you can do is approximate it with a large amount of pain and complexity (although in C++11 it's a bit easier). Therefore, this approach isn't recommended. C++ supports other programming paradigms relatively well, and IMHO should not be bent to paradigms it supports less well - in the end it will make unreadable code only the author understands.

Eli Bendersky
  • 263,248
  • 89
  • 350
  • 412
  • 18
    It's **NOT** fun programming FP in C++. For fun program FP with Lisp or Haskell – Eli Bendersky Dec 30 '09 at 18:02
  • 1
    I'd surely learn FP language someday. But now I don't have time for that. – Red Hyena Dec 30 '09 at 18:11
  • 13
    But I have to insist :-) It will take less time than learning how to do that in C++ – Eli Bendersky Dec 30 '09 at 18:15
  • Okay. I'll check out some FP language. Thanks for the response! – Red Hyena Dec 30 '09 at 18:52
  • 9
    I don't think this is fair. Sure, you can't completely eschew side-effects in C++, but you can go a long way towards adopting a functional approach. Books like Higher Order Perl show that functional approaches can be used in an imperative language. Moreover, various features of C++ make a functional style easier to adopt than in, say, C. – daf Dec 30 '09 at 19:29
  • 1
    @daf: Whether you can "go a long way toward adopting a functional approach" in C++, it's still not as well-supported as in a functional language. Nobody's even talking about completely eschewing side effects (the languages people are recommending, like OCaml and Scheme, are all impure). You can apply functional principles to C++ code, but it will be harder to learn those principles in the language. So I think this answer is closer than endorsing C++ as a functional language. And saying that it's easier to do than in C is pretty much damning with faint praise. – Chuck Dec 30 '09 at 19:43
  • 1
    So many times it has been said 'C++ can not do' in the past.. Even past STL style FP, you know the outcome. Go Phoenix that's the Spirit :) – rama-jka toti Dec 30 '09 at 19:44
  • 1
    I recommend scheme... it's one of the purest functional languages. You'll learn how to think functionally very quickly. – Mongoose Dec 30 '09 at 20:44
  • @daf: Perl is **far** from being an imperative language. It's a multi-paradigm language with first order functions that supports FP naturally – Eli Bendersky Dec 31 '09 at 16:37
  • 1
    Note that "Lisp" which most of the time means "Common Lisp", is not functional - it is multiparadigm and does not even guarantee TCO. OTOH, others lisp dialects like Scheme and Clojure are functional. – yati sagade May 14 '13 at 09:43
  • 1
    -1. C++ has had emulated "first class functions" since C++98 and with C++11 it's become even easier to define with the addition of lambdas. C++14 makes that even easier with polymorphic lambdas and the polymorphic functors in ``. The situation has changed quite tremendously since C++11 and it's shaping to get even better in the future. Not to mention that move semantics makes certain things more appealing. – Rapptz Aug 01 '14 at 03:27
  • @Rapptz: see my update. This answer was posted 5 years ago and it's time to move on. – Eli Bendersky Aug 01 '14 at 13:40
  • 1
    C++11 notwithstanding, the original answer is still accurate IMHO. Working extensively with both C++ and functional languages, I can attest that they are still universes apart. C++ syntax, type system, and low-level semantics are still in the way big time -- all fundamental issues that are not going away by adding yet more features to the language. Yes, you can emulate some functional techniques, but it is very verbose, very painful (especially with mistakes), and limited by the lack of GC, the lack of general tail-calls, the lack of pattern matching, and the lack of polymorphic type checking. – Andreas Rossberg Aug 01 '14 at 14:36
  • Negative. I did (read: we did) FP in C++ in an inv. bank and it works flawless. It's also way faster and needs much less support: easier to write test for and easier to argue when sg goes wrong. Self documenting and fun and you'll understand you don't need sw caches :). – lorro Jun 22 '16 at 19:40
  • I recommend OCaml, F# (which is also an OO language), or Haskell (which is a pure language). I do not recommend Lisp/Scheme because they are not FP languages. If you prefer Lisp-like languages, then Clojure is Lisp-like language which adds FP. Clojure targets JVM, and also can target .NET or transpile to JavaScript. Other options are Scala (which is also an OO language; and a JVM language), or Elm (a viable FP alternative to non-FP languages like CoffeeScript, TypeScript). My favorite in the above selection is F#. I hope C++ evolves into a functional-first FP kind of language. – Eljay Aug 12 '17 at 22:49
14

UPD Dec 2018

I've created a comprehensive list of materials where you can find articles, talks, screencasts, papers, libraries and showcases:

Functional Programming in C++


Consider my 4 research projects:

This project is a working prototype of 'Amber' game. The code demonstrates many of major functional concepts: immutability, lambdas, monads, combinators, pure functions, declarative code design. It uses Qt C++ and C++11 features.

For a quick example, see how tasks can be chained into one big task that will modify the Amber's world when it's applied:

const AmberTask tickOneAmberHour = [](const amber::Amber& amber)
{
    auto action1Res = magic::anyway(inflateShadowStorms, magic::wrap(amber));
    auto action2Res = magic::anyway(affectShadowStorms, action1Res);
    auto action3Res = magic::onFail(shadowStabilization, action2Res);
    auto action4Res = magic::anyway(tickWorldTime, action3Res);
    return action4Res.amber;
};

This is a showcase of generic functional lenses in C++. The implementatoin is built with using of Variadic Templates, some intresting (and valid) C++ hacks to make lenses composable and neat-looking. The library is just a demo for the talk and thus it provides only a few of most important combinators, namely: set(), view(), traverse(), bind(), infix literal combinator to, over() and other.

(Note that there exist the 'C++ Lenses' project: but it's not about real 'lenses', it's about class properties with getters and setters in sense of C# or Java properties.)

Quick example

Car car1 = {"x555xx", "Ford Focus", 0, {}};
Car car2 = {"y555yy", "Toyota Corolla", 10000, {}};

std::vector<Car> cars = {car1, car2};

auto zoomer = traversed<Car>() to modelL();

std::function<std::string(std::string)> variator = [](std::string) { return std::string("BMW x6"); };
std::vector<Car> result = over(zoomer, cars, variator);

QVERIFY(result.size() == 2);
QVERIFY(result[0].model == "BMW x6");
QVERIFY(result[1].model == "BMW x6");

You have probably heard about monads. Monads are everywhere in talks about functional programming now. It's a buzzword. But what about comonads? I presented 1D and 2D celullar automata with the concept of comonads under the hood. The aim was to show how easy it is to move from the single-flow code to the parallel one using std::future as a Par monad. The project also benchmarks and compares two these approaches.

Quick example

template <typename A, typename B>
UUB fmap(
    const func<B(UUA)>& f,
    const UUUUA& uuu)
{
    const func<UB(UUUA)> f2 = [=](const UUUA& uuu2)
    {
        UB newUt;
        newUt.position = uuu2.position;
        newUt.field = fp::map(f, uuu2.field);
        return newUt;
    };

    return { fp::map(f2, uuu.field), uuu.position };
}

This library is based on Free monad and some other advanced ideas of Functional Programming. Its interface is similar to Haskell's native STM library. Transactions are monadically composable, pure functional, and there is a lot of useful monadic combinators to make designing of concurrent model more convenient and powerful. I've implemented the Dining Philosophers problem using the library, and it works well. Here is a sample of some transaction for taking of forks by a philosopher:

STML<Unit> takeFork(const TFork& tFork) {
    return withTVar<Fork, Unit>(tFork, [=](const Fork& fork) {
       if (fork.state == ForkState::Free) {
           return writeTVar<Fork>(tFork, Fork {fork.name, ForkState:Taken});
       }
       else {
           return retry<Unit>();
       }
    });
}

STML<Unit> takeForks(const TForkPair& forks) {
    STML<Unit> lm = takeFork(forks.left);
    STML<Unit> rm = takeFork(forks.right);
    return sequence(lm, rm);
}
Alexander Granin
  • 963
  • 14
  • 20
5

I don't think that you can't to true, real, functional programming in C++; but it's certainly not the easiest or natural way to use it. Also, you might just use a couple of functional-like idioms and not the whole mindset (i.e. 'fluent style')

My advise would be to learn a functional language, maybe start with Scheme, then move to Haskell. Then use what you've learned when programming in C++. maybe you won't use an obvious functional style; but you might get the biggest advantages (i.e. using immutable structures).

Javier
  • 60,510
  • 8
  • 78
  • 126
  • as someone learning haskell, I'd be interested in knowing why you suggest scheme first. – Evan Carroll Dec 30 '09 at 18:04
  • I have seen some Scheme code before. It looks like all Chinese-Japanese to me. :| – Red Hyena Dec 30 '09 at 18:22
  • Okay. I'll check out some FP language. Thanks for the response! – Red Hyena Dec 30 '09 at 18:53
  • @EvanCarroll: maybe it's just how i learned them; but i find Scheme less surprising. Also there's some good (but old) introductory texts for Scheme, not so many (or not so well known) for other FP languages – Javier Dec 30 '09 at 19:31
  • @Jacon Johnson: yeah, the first sight of a new syntax (or lack of) can be upsetting, but it's really skin deep. The real meat is underneath (but some are made easier by the lack of syntax). Still, there's nothing magical about Scheme, just pick any FP language that seems approachable. – Javier Dec 30 '09 at 19:33
1

There is a book called Functional C by Pieter Hartel and Henk Muller which might help. If it still available. A link to some info on it is here. IIRC it wasn't too bad.

rvirding
  • 20,848
  • 2
  • 37
  • 56
  • According to the description, that book teaches imperative programming to people coming from functional languages. Not how to do functional programming in C (which would be quite a bit more painful than doing it in C++, I'd imagine). – sepp2k Dec 31 '09 at 13:35
  • Ostensibly this is so, but there is nothing to stop you using in the opposite direction. It works quite well for that and does give you some indications how to program C in a functional style. – rvirding Jan 01 '10 at 19:27
0

Probably a bit late but for anyone else looking - I use lua as a functional programming extension to C++ and it's great. lua

daven11
  • 2,905
  • 3
  • 26
  • 43
  • 1
    Is this really a suggestion to just use another language? – CyberFox Jun 22 '16 at 06:44
  • This answer should expound upon how Lua is well-integrated within C++ (more than merely invoking a subroutine/function/method/rose-by-any-other-name), especially to accomplish using Lua for FP while using C++ for nonFP somehow in some kind of synergistic interplay. – Andreas ZUERCHER Apr 06 '21 at 18:45