Skip to content

randrewy/Streams

Repository files navigation

Build Status GitHub license Coverage Status

Streams++

Streams++ is a C++14 library inspired by Rust-lang Iterator trait and Java 8 Streams API. A stream represents a sequence of elements that come from some source. The stream itselt and most operations upon its elements are lazy, so nothing is evaluated until it has to be done. This allows to perform computation in a functional style by chaining operations stream supports.

Installation

Streams++ is a header only library, so just include Streams.h. It has no external dependencies, but uses std::optional<T> type from <experimental/optional>.

If you are using Visual C++ it's almost sure there is no <experimental/optional> header. In that case the library relies on akrzemi1/Optional library. You'll need extra steps after pulling this repository:

git submodule init
git submodule update

You can use cmake to build tests and examples alltogeather.

Examples

Creating a stream from a collection

std::vector<int> vec {/*...*/};
auto stream = streams::from(vec);

Sum of squares of multiples of 17

int sum = streams::from(vec) // you can use a 'stream' created before
    .filter([](auto& e) {return e % 17 == 0; })
    .map([](auto& e) { return e*e; })
    .fold(0, std::plus<>{});

First 5 roman numbers with more than 10 'digits'

std::string to_roman(size_t i);

streams::generate::counter(1)
    .map(to_roman)
    .enumerate()
    .filter([](auto& e) {return e.v.length() > 10; })
    .take(5)
    .forEach([](auto& e) { std::cout << e.i + 1 << " == " << e.v << std::endl; });

enumerate() will stream struct with index and value members. In case you want to use idiomatic std::tuple call enumerateTup() here.

If you are curious the result is:

388 == CCCLXXXVIII
788 == DCCLXXXVIII
838 == DCCCXXXVIII
878 == DCCCLXXVIII
883 == DCCCLXXXIII

Under the hood

Streams are designed to be fast and lightweight proxy objects. Every stream is a different class with statically dispatched methods. More than that, a stream

  • doesn't own the underlying collection;
  • doesn't modify the underlying collection;
  • doesn't allocate memory on the heap;
  • never throws exceptions unless it's thrown from inside user code;
  • is valid to copy, though the state will also be copied.

As a proxy object, stream should never outlive its source.

Stream is a single-use object. It can't be reset or used again after its source is depleted. Actually, using an exhausted stream is a valid operation, but the stream will remain empty forever.

Tests

You'll need googletest. Simply run

$ mkdir build
$ cd build
$ cmake ..
$ make
$ ctest -VV

or use generated project file on Windows.

About

Lazy functional-like computation library

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published