Similar to this effort, Eric Niebler's range library [1,2] aims at improving algorithm composability. The range library offers both an eager and lazy API. This is the lazy version (views):
int sum = accumulate(view::ints(1)
| view::transform([](int i) {return i * i;})
| view::take(10), 0);
And this the eager (via actions):
extern std::vector<int> read_data();
std::vector<int> vi = read_data(); action::unique;
vi = std::move(vi) | action::sort | action::unique;
Eric puts in a lot of effort to make this library part of the C++ standard (see proposal N4128 [3]).
Using "|" to indicate flow of data from producer to consumer is idiomatic, if you consider the Unix command line. Personally, I find this kind of operator overloading tasteful and sensical.
let total = (1..).map(|x| x*x).take(10).fold(0, |acc, x| acc+x);
You could replace the fold with ".sum()" if you use the unstable std::iter::AdditiveIterator. Or you could incorporate the squaring map into the fold, but then we're no longer comparing the same thing.
int total = recurrence!"n+1"(0)
.map!(x => x*x)
.take(10)
.sum();
Replacing that last sum() with reduce() from std.parellelism and you can sum them using multiple threads (obviously not useful with a set this small but the documentation for reduce() coincidentally includes a benchmark for the sum of squares running 2.5x faster when done in parallel).
You beat me to the J solution, but here it is in APL:
+/2*⍨⍳10
No need for increment, since index is set to start at 1. You can set it to 0 too, if you work that way.
+ addition
/ reduce
2 (to be fed to exponential operator * for square)
* exponential
⍨ commute
⍳ iota - index generator
I would consider C++ with this library over Haskell just because you get the world of C++, but with a bit more of the expressiveness I like in the functional languages.
Syntax is like getting used to math symbols, but once you do, you can really do a lot with a little - very expressive. I find myself in the J interpreter or APL workspace to hack away at solutions much more so than in any other language. I am not a web developer.
don't confuse standard libraries, libraries and languages :)
Prelude is functional, C++ STL and the C library are imperative.
There is a valid argument that a 'good ol' fashioned' bit of procedural code (for loop) makes this same algorithm easier to read than either of these (it certainly makes it shorter), since it tells you explicitly what it is doing rather than assuming (usually a safe assumption) that programmers can understand and trust things like sum, map and take/limit.
i'm thinking of something like:
int iTotal = 0;
for( int i = 0; i < 10; ++i )
{
iTotal += i * i;
}
That argument is not invalid, but the counter-argument is that the functional version does a much better job of capturing the intention of the code, rather than the procedure of it. The intention is to get the sum of the squares of the first 10 numbers counting from 1. My gut tells me that I have fewer bugs when I'm capturing intention rather than process, but I won't claim that it's definitely true.
(Not to say this is an example of bug-due-to-process-over-intention, but you do have a bug – you're summing from 0 to 9 instead of 1 to 10.)
why is it not valid? these things are part of the libraries involved. as languages both Haskell and C++ are extremely free form to the point where you can abuse them into behaving like domain specific languages.
or do you mean the bit about it being less code and easier to read?
well done on catching the bug. :)
this is my own fault for being sloppy and not paying attention.
You (understandably, due to the double-negative) misread! I said it is not invalid. Which was really a weaselly way of saying that it's valid but I don't really agree with it – sorry about that!
It would be nice to see a performance comparison here. I wouldn't be surprised if Haskell would win, given the fact that lazy evaluation is its bread and butter.
I'm sure that Haskell is fabulously performant here, but I'm not sure that it would be either significantly faster or slower than a C++ library that properly implements laziness. I can't speak for Streams, but Rust makes use of lazy iterators pervasively (all implemented entirely in the stdlib), and I'd expect the equivalent Rust code:
let total = (1..).map(|x| x*x).take(10).sum();
to have no more overhead than the ideal Haskell code (though I could be oblivious to some very important GHC optimization... when posed this question my Haskell-using friends simply respond with "it's complicated").
It's certainly complicated and my answer probably does not apply to such a trivial example code that is using mostly stdlib functions. But the potential gain for Haskell is with loop fusion. The user could implement all of those functions themselves (sum, take, etc) and then loop fusion will bind them into a single performant loop that the lower optimizers will turn into a straight-line code, whereas in procedural languages only stdlib functions and certain patterns of general functions get the fusion treatment. Worse, throw in an unfortunate alias into the procedure and the whole thing collapses into sequential loops.
Hell, if anything on a short sequence the naive (one loop at a time) approach might be faster if it keeps the instruction and data caches more coherent.
Laziness slows everything down by a constant factor. In this example, Haskell would perform about the same as C++, because of optimizations that turn operations on linked list cells into loops (arriving at a result much like the external iterators of Rust and the expression template based iterators of C++).
I would expect that the project also uses const iterators (cbegin, cend, etc) which didn't make it into C++11, and probably make_unique<T>, which also never made it into C++11, even though it very well would have (if it had been implemented before the cutoff date).
In any case, most of C++14 (outside of automatic lambda parameter deduction) can be emulated or straight copied into C++ using C++11. Most of the implementations of library specific things can be found at [1], so if you find a feature in C++14 that you're missing, go ahead and search the draft standard files (most of which are verbatim the same implementation) and copy into your own project.
To be fair though, one of the bigger features of C++11 / C++14 brings to the table is just easier template / std::algorithm usage (via lambdas), and smart pointers. Beyond that, most things aren't as necessary or as widespread in use even within std / STL. So for the most part, if you (or parent) has been interested in learning some modern C++, for the most part you can start leveraging a lot of the more useful tools / tricks immediately, even if the compilers haven't fully implemented C++14 yet [2].
[2] My understanding is that libc++ and clang are fully caught up, but g++ / libstdc++ won't be 100% C++14 compliant until after gcc-5.0. Either way, the corner cases exist, but for the most part you can take advantage of most of the great areas of modern C++ without waiting for gcc-5.0.
> I would expect that the project also uses const iterators (cbegin, cend, etc) which didn't make it into C++11, and probably make_unique<T>, which also never made it into C++11, even though it very well would have (if it had been implemented before the cutoff date).
Const iterators in the form of cbegin() and cend() member functions on the standard containers were part of C++11, I'm pretty sure. It's either that or the C++ Primer 5e included some post-C++11 things in it.
What was missing from C++11, and probably an oversight, was std::cbegin() and std::cend() free functions, a la std::begin() and std::end(), for overloading and C arrays and so forth.
Facebook's folly::gen library (some examples at [1]) is another approach at this idea. It also has some nice features like buffered file reading, fork-join parallelism, etc.
[1] https://github.com/ericniebler/range-v3
[2] User Manual with code examples: https://ericniebler.github.io/range-v3/index.html
[3] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n412...