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.
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!
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.
cat
or eager
for an example transducer that uses reduce_nested
. 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...)
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.
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
.
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
.
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
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.
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.
zug::
make_reductor
(ReducingFnT &&step, InitialStateT &&state, InputTs&&... ins)¶Constructs a reductor
object with deduced argument types.
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.
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… >
zug::
empty_reductor
¶Reductor object that does not require inputs to be fed at construction time. In some cases though, reductor
can perform better.
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
() const¶Completes and returns the state of the reduction. The operation os move aware.
current
() const¶Peeks at the current visible state of the reduction. The operation is move aware.
current
(T &&x)¶Changes the current visible state of the reduction to be the value x
;
operator()
(InputTs2&&... ins)¶Evaluates the next step of the reduction, passing the inputs ins
to the reducing function.
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.