Hacker News new | past | comments | ask | show | jobs | submit login
Functional Programming in C++ (madhukaraphatak.com)
47 points by phatak-dev on Nov 16, 2014 | hide | past | favorite | 14 comments



The main thing missing in C++ to do functional programming, as mentioned by John Carmack in http://gamasutra.com/view/news/169296/Indepth_Functional_pro... is lack of a 'pure' keyword to enforce it.

Experience with the 'pure' keyword in D has been overwhelmingly positive.


Doesn't constexpr fill some of the purpose?


Yes, it does.


Well,why isnt D that popular? I wonder.

edit: genuine question.


C++ is steadily adopting D features :-)


Because C++ programmers are masochists?


I like the idea of functional programming in C++, but unfortunately, you would have to write an entirely different (non-standard) library for that to work. For example, from the article:

  template <typename Collection,typename unop>
  void for_each(Collection col, unop op){
    std::for_each(col.begin(),col.end(),op);
  }
...I like the pass-by-value syntax here, but it just won't work with the standard library, at least not the one in C++14. If you pass a vector into this function, you'll be creating a copy of the vector (!), then operating on the copy of the vector (!!). Then there is the question of what for_each does if it isn't manipulating state or performing I/O. In either case, you would not want an 'unop', you would want some sort of monad.

For a more complete perspective on this sort of thing, I recommend Eric Neibler's blog and Bartosz Milewski's blog. Here's somewhere to start. You'll find Neibler's blog linked from there:

http://bartoszmilewski.com/2014/10/17/c-ranges-are-pure-mona...


Actually the up side to value semantics is that it can take full advantage of move operations, so that if operating on an l-value your code only need copy the data the first time, then move kicks in for the rest of the chain... (i.e., mydata | filter(f) | reverse() | take(10) - only the filter() call will create the copy). And if you are operating on an rvalue no copies will be made at all.

Have a look at this: https://www.youtube.com/watch?v=YJIaGRDIyEE

Eric Neibler's approach (which I am really looking forward to!) is to state that range operations should never take ownership of the original data and therefore operations should be performed lazily. This prevents the rvalue optimisation, but enables lazy evaluation.

Its just a trade-off, but the value semantics approach isnt as bad as you might think...

edit: on further inspection the last paragraph of the article mentions this but doesnt go into detail.


Since it is a template you could always use universal references to avoid copying where not needed:

    template <typename Collection,typename unop>
    void for_each(Collection&& col, unop op){
      std::for_each(col.begin(),col.end(),op);
    }
I'm happy to see more people reading Bartosz, I find his blog very interesting. One point to emphasise about that particular post is that the proposed range library he discusses is already available today, and has been for some time, in the much overlooked boost.Range library.


> With modern C++ you can use value semantics with move semantics to get same performance as pass by reference.

That's overly simplistic. To enjoy the benefits of move semantics you need something to move from. If you call for_each from the article with an lvalue, you will end up making a copy (and it'll be up to the compiler to do something about that).


> Also you can use smart pointers to do automatic garbage collection.

Not quite. Smart pointers do automatic reference counting, which doesn't use a garbage collector.


Well, reference counting is a form of garbage collection, just not a very good one.

It is incomplete in the sense cycles are not collected, one would need extra machinery for those. It is also not great about throughput, a part of the problem is that it dirties the cache too much. Locking the count (or avoiding it somehow) is another issue. On the other hand for many use cases better latencies are achieved with reference counting than with alternative forms of garbage collection, (but this depends on use cases).

If runtime data cannot have have cycles, garbage is not created at a phenomenal rate and you are quite worried about GC pauses, then reference counting is often a cheap and effective solution.

Regardless, it sure is garbage collection.


I think he is referring to scoped pointers.


Oh god, why.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: