
C++ Streams - zyngaro
http://jscheiny.github.io/Streams/
======
mavam
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]).

[1]
[https://github.com/ericniebler/range-v3](https://github.com/ericniebler/range-v3)

[2] User Manual with code examples:
[https://ericniebler.github.io/range-v3/index.html](https://ericniebler.github.io/range-v3/index.html)

[3] [http://www.open-
std.org/jtc1/sc22/wg21/docs/papers/2014/n412...](http://www.open-
std.org/jtc1/sc22/wg21/docs/papers/2014/n4128.html)

~~~
tonyedgecombe
I really dislike the use of operator overloading for things like this, I
prefer a more verbose but idiomatic solution.

~~~
scott_s
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.

------
1234567890123
Just for comparison, in Haskell:

    
    
      total = sum $ take 10 (map (\x->x*x) [1..])
    

For this C++ code:

    
    
      int total = MakeStream::counter(1)
          | map_([] (int x) { return x * x; })
          | limit(10)
          | sum();
    

C++ code doesn't look that bad!

~~~
timtadh
While we are at it Python:

    
    
        >>> sum(x*x for x in xrange(1,11))
        385
    

You could use a map in Python as well, but really, the generator expression is
much cleaner:

    
    
        >>> sum(map(lambda x: x*x, xrange(1,11)))
        385

~~~
jlarocco
Those compute the same value, but I think the point of the C++ stream version
is to compute the value using a lazily evaluated infinite list.

The C++ equivalent of your Python would be something like:

    
    
        typedef boost::counting_iterator<int> ci;
        auto sum = std::accumulate(ci(0), ci(10), 0, [](auto x, auto y) { return x + (y*y); });
    

No special streaming library required.

------
easytiger
Err, you can't call it that if the std library already has a completely
unrelated core concept with the same name.

~~~
stinos
A good point actually. 'streams' makes me think of a lot things, but not one
of those comes close to what is shown in the samples

------
corysama
Very nice. I'm interested to know what features of C++14 are used that are not
available in C++11.

~~~
__float
A very (very) quick look gives an obvious answer of return type deduction and
auto in lambda parameters (so, generic lambdas).

It's definitely possible (même likely?) there are other more subtle things in
use too.

~~~
ThatGeoGuy
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].

[1] [https://isocpp.org/files/papers/](https://isocpp.org/files/papers/)

[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.

~~~
tomjakubowski
> 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.

------
ajtulloch
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/facebook/folly/blob/75278c6326af4e6a81b87...](https://github.com/facebook/folly/blob/75278c6326af4e6a81b8761acb5e24f6442dfa8f/folly/gen/test/BaseTest.cpp)

------
millstone
I'm not able to scroll the left sidebar in the docs page
([http://jscheiny.github.io/Streams/api.html](http://jscheiny.github.io/Streams/api.html)).
Using Safari on OS X Yosemite.

~~~
caipre
Working here, Firefox + Yosemite.

Tried Safari, it's working as well.

------
hatred
Looks slightly similar to Boost Range Adaptors ?

[http://www.boost.org/doc/libs/1_57_0/libs/range/doc/html/ran...](http://www.boost.org/doc/libs/1_57_0/libs/range/doc/html/range/reference/adaptors.html)

------
g1236627
Show some compiler errors or it did not happen.

------
jheriko
isn't this name confusing?

interesting stuff... although i do not enjoy the novel operator overloading,
it does keep it tidy.

------
taternuts
In the second example, you define `next_collatz`, but pass in `collatz_next`

------
lfj
On a side note, the page has 40 H1 headers. Yikes!

