Processes

A transducer in itself describes a transformation between abstract sequences, but it is completely agnostic of the physical or temporal nature of that sequence. We call a process the mechanism that actually feeds data in and out out a transducer.

In this section, we describe several processes provided by the library. A few of them are processes for processing C++ iterator based sequences and ranges. Some, like reductor, may help implementing your own processes. For an example of a third-party library that implements its own transducible components, check the cursors module in Lager.

reduce

template <typename ReducingFnT, typename StateT, typename… InputRangeTs>
auto zug::reduce(ReducingFnT &&step, StateT &&state, InputRangeTs&&... ranges)

Similar to std::accumulate and clojure.core/reduce.

Evaluates the reducing function step over every element of the input ranges, passing as first argument always its last returned state.

Unlike std::accumulate, this reduces over a range (doesn’t take two distinct iterators) and can reduce over several ranges at the same time. Also note the different order of arguments.

Also, reduce supports reducing functions with the state interface described in the Design section. This means that the reducing function can wrap the state in the first iteration, and the state can signal early termination. This means, also, that this function can also take no input range. In this case, the reducing function will be evaluated indefinitelly, and the reducing function may generates its own data until it eventually terminates.

Note

This function uses state_complete before returning the final state, thus returning a state of type StateT. Use reduce_nested when this is not desirable.

Warning

Reduce assumes that the ranges that are passed actually hold the values. When the ranges are pased as r-values, the elements will be moved from the range into the reducing function. Extra care has to be taken when using range adaptors or views—if the adapted container needs to be used after the reduction, make sure to pass the view as an l-value, by giving it a name. Example:

using namespace boost::range::adaptors;
auto x = std::vector<std::string>{ "foo", ... };
reduce(..., x | reversed);
std::cout << x[0] << std::endl; // CRASH!

To avoid this, you may give names to intermediate adaptors:

using namespace boost::range::adaptors;
auto x = std::vector<std::string>{ "foo", ... };
auto y = x | reversed;
reduce(..., y);
std::cout << x[0] << std::endl; // fine!

reduce_nested

template <typename ReducingFnT, typename StateT, typename… InputRangeTs>
auto zug::reduce_nested(ReducingFnT &&step, StateT &&state, InputRangeTs&&... ranges)

Similar to reduce, but it does not unwrap the final state before returning it. This is useful when calling performing a reduction recursively within a transducer.

See
The implementation of cat or eager for an example transducer that uses reduce_nested.

transduce

template <typename XformT, typename ReducingFnT, typename StateT, typename… InputRangeTs>
auto zug::transduce(XformT &&xform, ReducingFnT &&step, StateT &&state, InputRangeTs&&... ranges)

Similar to clojure.core/transduce.

Given a transducer xform, this is equivalent to: reduce(xform(step), state, ranges...)

run

template <typename XformT, typename… InputRangeTs>
void zug::run(XformT &&xform, InputRangeTs&&... ranges)

Runs a transducer composed with no significant reduction over zero of more ranges. It is useful to execute a transducer when we are only interested on its side effects.

into

template <typename CollectionT, typename XformT, typename… InputRangeTs>
auto zug::into(CollectionT &&col, XformT &&xform, InputRangeTs&&... ranges)

Transduces the input ranges using xform, storing the results in the collection col, which is also returned.

The results are stored in col using push_back(). If transducer has multiple output arguments, they are combined in a std::tuple.

template <typename XformT, typename… InputRangeTs>
auto zug::into_vector(XformT &&xform, InputRangeTs&&... ranges)

Transduces the input ranges using xform, storing the results in a vector that is returned.

The value type of the vector is automatically deduced from the application of the transducer to the input ranges. If there are multiple arguments in the outputs from the transducer, they are combined in an std::tuple.

sequence

template <typename ValueT = detail::deduce_value_type, typename XformT, typename… RangeTs>
auto zug::sequence(XformT &&xform, const RangeTs&... ranges)

Returns a sequence_range values producing an iterable range out of a transducer, in the spirit of clojure.core/sequence

template <typename ValueT, typename XformT, typename… RangeTs>
struct zug::sequence_range

Range adaptor that transduces the ranges in RangeTs with the transducer XformT, producing values of ValueT. It also works with no range, as a generator.

Tip

The transducer is processed lazily. It is ok to adapt infinite ranges or infinite generators!

Note

There is no shared data between the range iterators excepting the adapted ranges, for which a const reference is kept. This means that it is safe to copy the iterators around and use them from different threads. It is also safe to use the iterators after the parent sequence_range is destroyed, but the adapted ranges should still be kept alive.

Warning

The transducer is processed every time for each iterator. Thus, any side effects the transducer might cause will be produced whenever we run on each iterator of the range.

reductor

Reductors encapsulate a reducing function and its reduction state in a more object oriented interface. It can be useful when implementing your own processes that supports transducers.


template <typename ReducingFnT, typename InitialStateT, typename… InputTs>
auto zug::make_reductor(ReducingFnT &&step, InitialStateT &&state, InputTs&&... ins)

Constructs a reductor object with deduced argument types.

template <typename… InputTs, typename ReducingFnT, typename InitialStateT>
auto zug::make_empty_reductor(ReducingFnT &&step, InitialStateT &&state)

Constructs an empty_reductor object with deduced argument types. The InputTs over which the reductor functions have to be passed explicitly though.

template <typename ReducingFnT, typename InitialStateT, typename… InputTs>
struct zug::reductor

Function object that performs a reduction using a reducing function of type ReducingFnT, an initial state of type of type InitialStateT and inputs of types InputTs....

The function object can be called with arguments converibles to InputTs... to step the reduction. If the reductor object is const, it will return a new value representing the advanced state. Otherwise it performs the reduction in place and returns a reference to itself. See reductor_base for details on the interface.

This object requires an initial input to be pased to the constructor. If no input is available at construction time, use empty_reductor instead.

Inherits from zug::reductor_base< ReducingFnT, std::result_of_t< ReducingFnT(InitialStateT, InputTs…)>, InputTs… >

template <typename ReducingFnT, typename InitialStateT, typename… InputTs>
struct zug::empty_reductor

Reductor object that does not require inputs to be fed at construction time. In some cases though, reductor can perform better.

Inherits from zug::reductor_base< detail::caller< std::decay_t< ReducingFnT > >, std::decay_t< skip_result_t< ReducingFnT, InitialStateT, InputTs… > >, InputTs… >

template <typename ReducingFnT, typename StateT, typename… InputTs>
struct zug::reductor_base

Common reductor interface. This is an abstract type, use reductor and empty_reductor concrete types.

Public Functions

operator bool() const

Returns whether the reductor will produce more values.

complete_type complete() const

Completes and returns the state of the reduction. The operation os move aware.

complete_type current() const

Peeks at the current visible state of the reduction. The operation is move aware.

template <typename T>
void current(T &&x)

Changes the current visible state of the reduction to be the value x;

template <typename… InputTs2>
reductor_base &operator()(InputTs2&&... ins)

Evaluates the next step of the reduction, passing the inputs ins to the reducing function.

Note
When operated on a const object, the it returns a new reductor object. Otherwise, the operation is performed in-place and the object itself is returned. The operation is move-aware.