What I find painful about writing pseudo-functional C++ using <algorithm> and other tricks is that you have to allocate storage for intermediate values. This makes C++ algorithms a lot less composable than similar things in other languages.<p>So if I wanted to do something like (in Haskell):<p><pre><code> sumOfOddSquares xs = sum . map (^2) . filter odd $ xs
</code></pre>
In C++, I would need to allocate temporary storage for the intermediate values.<p><pre><code> std::vector odd_numbers;
std::copy_if(xs.begin(), xs.end(), back_inserter(odd_numbers), isOdd);
std::transform(odd_numbers.begin(), odd_numbers.end(), odd_numbers.begin(), square);
std::accumulate(odd_numbers.begin(), odd_numbers.end(), 0, plus);
</code></pre>
This becomes quite painful very quickly. You can use solutions like boost::filter_iterator, but soon you're knee deep in C++ templates and the long compile times and awful error messages that follow.<p>The example above is a bit contrived since it can be easily be done with a single accumulate, but you get the idea...<p><pre><code> std::accumulate(xs.begin(), xs.end(), 0,
[](int sum, int i) { return sum + ((i&1) ? i*i : 0); });
</code></pre>
So while you can have lots of fun with <algorithm>, it's quite limited in what it can do.
<algorithm> is so 90s. In C++14 you'll be able to do this:<p><pre><code> auto square_copy = [](auto v) {
for (auto& e: v) { e *= e; }
return v;
};
</code></pre>
Another option:<p><pre><code> auto square = [](auto& v) { v *= v; };
auto map = [](auto range, auto fun) {
transform (begin(range), end(range), fun);
return range;
};
vector<int> vec = {1,2,3,4,5,6};
auto squared = map (vec, square);
</code></pre>
Note that, in both of these cases, if you use std::move() to gift a container to these functions, they will not actually allocate any memory and will effectively operate in-place.
Using Facebook's `folly::gen` library [1], you can get it down to:<p><pre><code> vector<int> squareVec3(const vector<int>& v) {
return from(v) | mapped([](int i){ return i * i; }) | as<vector>();
}
</code></pre>
which is pretty slick.
There are a bunch of the usual LINQ/functional operators in
`folly::gen` that are quite nice. As an example, to filter out the odd elements of `v`, you can do<p><pre><code> vector<int> squareVecFiltered(const vector<int>& v) {
return from(v)
| filter([](int i){ return i % 2 == 0; })
| mapped([](int i){ return i * i; })
| as<vector>();
}
</code></pre>
<a href="https://github.com/facebook/folly/tree/master/folly/gen" rel="nofollow">https://github.com/facebook/folly/tree/master/folly/gen</a>
C++ is evolving at a kind of breakneck pace lately, and it's already a lot different from the language it used to be. Auto, range loops, and lambdas are making it much more pleasant to work in while still maintaining a lot of performance advantages.<p>I know it's pretty popular to hate on C++, but I'm pretty excited about where it's going, personally.
I'm not really sure why references are being used here, if you're just making a copy straight-away.<p><pre><code> vector<int> square(vector<int> vcopy)
{
for (int &i : vcopy)
i *= i;
return vcopy;
}
</code></pre>
is shorter, (IMO) much more readable, and on my tests, measurably faster than the reference version. If you really want the std::accumulate version,<p><pre><code> vector<int> square(vector<int> vcopy)
{
accumulate(begin(vcopy), end(vcopy), begin(vcopy),
[](int i) { return i * i; });
return vcopy;
}
</code></pre>
works just as well.<p>Still, I guess it's beside the point.
After coding in languages in like Scala/Python for a while, it took me a while to parse this. Scala equivalent: `def square(a: List[Int]) = a map {i => i*i}`
Convenience overloads for common use cases (iterating over the full vector, accumulating on a default-constructed accumulator, etc) would be great to have as standard. Are there and I have missed them? If not, what's the rationale? (this goes for the STL in general, not specifically these high order algos)
Just as a side note: if you're looking to write a convenience wrapper like the author's transformVec, do not have it take the function as `const function<T(T)>&`. Instead, do something like:<p><pre><code> template <typename T, typename F>
vector<T> transformVec(const vector<T>& v, F op)
</code></pre>
Using std::function in a case where you just want something callable just makes the optimizer's job a lot harder. Using std::function is a good idea if you actually need type erasure (for example if you want to pass something callable to a function that is <i>not</i> a template).
The author probably thinks that all versions are equally fast, but in fact they are just equally slow. Neither gcc 4.8 nor icc 14 can use vectorization for this loop (likely because of aliasing).
`result = [i * i for i in v]` looks much more readable to me.<p>What if you need to square every other element? copy_if and transform then don't look so pretty anymore. `result = [i * i for i in v if i % 2 == 0]` is still more readable.<p>What if you need to do something else and you don't know if there is a transform like function for it?
It seems like it's the loop itself that is redundant. Why couldn't I just do:<p><pre><code> squaredVec = vec * vec
</code></pre>
or<p><pre><code> squaredVec = vec ^ 2</code></pre>