Efficient and flexible C++ implementation of transducers. More...
Classes | |
class | any_state |
Polymorphically holds any value implementing the state_traits . More... | |
struct | emplace_back_rf_t |
Reducing function that emplaces back at the collection that is uses as state. More... | |
struct | empty_reductor_fn |
Reductor_Fn object that does not require inputs to be fed at construction time. More... | |
struct | empty_reductor_fn< ReducingFnT, InitialStateT, meta::pack< InputTs... > > |
struct | first_rf_t |
Reducing function that always returns the initial state. More... | |
struct | is_skip_state |
struct | is_skip_state< skip_state< SkippedT, CalledT > > |
struct | is_state_wrapper |
Metafunction returning whether StateT is a, or reference to, a state_wrapper instantiation. More... | |
struct | is_state_wrapper< _, state_wrapper< T, S, D > > |
struct | last_rf_t |
Reducing function that produces the tuplification of the last inputs it received. More... | |
struct | maybe_reduced_tag |
Tag for maybe_reduced state wrapper. More... | |
struct | no_tag |
Default tag for state_wrapper . More... | |
struct | output_of |
Metafunction that given a transducer XformT and some inputs InputTs , returns the type of the outputs of the transducer, wrapped in a meta::pack . More... | |
struct | output_of< XformT, meta::pack< InputTs... > > |
struct | output_rf_t |
Reducing function that outputs through the iterator that is carried as state. More... | |
struct | reductor_fn |
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... . More... | |
struct | reductor_fn_base |
Common reductor interface. More... | |
struct | result_of |
Metafunction that given a transducer XformT and some inputs InputTs , returns the type of the output of the transducer, combined as combined in a single result with tuplify . More... | |
struct | result_of< XformT, meta::pack< InputTs... > > |
struct | sequence_range |
Range adaptor that transduces the ranges in RangeTs with the transducer XformT , producing values of ValueT . More... | |
struct | skip_result |
Metafunction that returns a type that can hold both values of type skipped_t = StateT and wrapped_t = declval<ReducingFnT>(declval<StateT>(), declval<InputTs>()...) More... | |
struct | skip_state |
Type-safe union type that can hold values of both SkippedT and CalledT types. More... | |
struct | state_traits |
Interface for a type specializing the State concept. More... | |
struct | state_traits< any_state > |
struct | state_traits< skip_state< SkippedT, CalledT > > |
struct | state_traits< state_wrapper< TagT, StateT, DataT > > |
State traits specialization for state_wrapper . More... | |
struct | state_wrapper |
A decorator for the accumulator of a reduction. More... | |
struct | transducer_impl |
Utility to write simple transducers easily. More... | |
Typedefs | |
template<typename T > | |
using | maybe_reduced = state_wrapper< maybe_reduced_tag, T, bool > |
State wrapper for transducers that may want to signal that the reduction is finished. More... | |
template<typename ReducingFnT , typename StateT , typename... InputTs> | |
using | skip_result_t = typename skip_result< ReducingFnT, StateT, InputTs... >::type |
template<typename T > | |
using | state_traits_t = state_traits< estd::decay_t< T > > |
using | cat_t = transducer_impl< detail::cat_rf_gen > |
template<typename T > | |
using | chainr_t = transducer_impl< detail::chainr_rf_gen, T > |
template<typename T > | |
using | chainl_t = transducer_impl< detail::chainl_rf_gen, T > |
template<typename T1 , typename T2 > | |
using | count_t = transducer_impl< detail::count_rf_gen, T1, T2 > |
template<typename T > | |
using | cycle_t = transducer_impl< detail::cycle_rf_gen, T > |
using | dedupe_t = transducer_impl< detail::dedupe_rf_gen > |
using | distinct_t = transducer_impl< detail::distinct_rf_gen > |
template<typename T > | |
using | drop_t = transducer_impl< detail::drop_rf_gen, T > |
template<typename T > | |
using | drop_while_t = transducer_impl< detail::drop_while_rf_gen, T > |
template<typename T > | |
using | each_t = transducer_impl< detail::each_rf_gen, T > |
template<typename T > | |
using | eager_t = transducer_impl< detail::eager_rf_gen, T > |
using | sorted_t = eager_t< detail::sorted_range_t > |
using | reversed_t = eager_t< detail::reversed_range_t > |
template<typename T > | |
using | enumerate_t = transducer_impl< detail::enumerate_rf_gen, T > |
template<typename T > | |
using | filter_t = transducer_impl< detail::filter_rf_gen, T > |
using | interleave_t = transducer_impl< detail::interleave_rf_gen > |
template<typename T1 , typename T2 > | |
using | interpose_t = transducer_impl< detail::interpose_rf_gen, T1, T2 > |
template<typename T > | |
using | iter_t = transducer_impl< detail::iter_rf_gen, T > |
template<typename T > | |
using | map_t = transducer_impl< detail::map_rf_gen, T > |
template<typename T > | |
using | partition_t = transducer_impl< detail::partition_rf_gen, T > |
template<typename T > | |
using | partition_by_t = transducer_impl< detail::partition_by_rf_gen, T > |
template<typename T > | |
using | product_t = transducer_impl< detail::product_rf_gen, T > |
template<typename T , typename InputStreamRefT > | |
using | read_t = transducer_impl< detail::read_rf_gen< T >, InputStreamRefT > |
template<typename InputStreamRefT , typename BufferT > | |
using | readbuf_t = transducer_impl< detail::readbuf_rf_gen, InputStreamRefT, BufferT > |
template<typename T > | |
using | repeat_t = transducer_impl< detail::repeat_rf_gen, T > |
template<typename T > | |
using | sink_t = transducer_impl< detail::sink_rf_gen, T > |
template<typename T > | |
using | take_t = transducer_impl< detail::take_rf_gen, T > |
template<typename T > | |
using | take_nth_t = transducer_impl< detail::take_nth_rf_gen, T > |
template<typename T > | |
using | take_while_t = transducer_impl< detail::take_while_rf_gen, T > |
template<typename InputT = meta::pack<>, typename OutputT = InputT> | |
using | transducer = transducer_impl< meta::unpack< detail::transducer_rf_gen, OutputT >, detail::transducer_function_t< InputT, OutputT > > |
Type erased transducer. More... | |
using | unzip_t = transducer_impl< detail::unzip_rf_gen > |
template<typename OutputStreamRefT , typename InSeparatorT , typename ArgSeparatorT > | |
using | write_t = transducer_impl< detail::write_rf_gen, OutputStreamRefT, InSeparatorT, ArgSeparatorT > |
template<typename OutputStreamRefT > | |
using | writebuf_t = transducer_impl< detail::writebuf_rf_gen, OutputStreamRefT > |
Functions | |
ABL_CONCEPT_SPEC (State) | |
Concept for a type that can be used as a state of a reducing function. More... | |
ABL_CONCEPT_SPEC (Reducing_function) | |
Concept for a function that can be used with reduce for a specific state and inputs. More... | |
ABL_CONCEPT_SPEC (Transducer) | |
Concept for a transducer , this is, a function that takes a reducing function as an argument, and decorates it returning a new reducing function. More... | |
ABL_CONCEPT_SPEC (Transparent_transducer) | |
Concept for a transducer that can be applied over any arguments. More... | |
template<typename CollectionT , typename XformT , typename... InputRangeTs> | |
auto | into (CollectionT &&col, XformT &&xform, InputRangeTs &&...ranges) -> CollectionT && |
Similar to clojure.core/into$4. More... | |
template<typename XformT , typename... InputRangeTs> | |
auto | into_vector (XformT &&xform, InputRangeTs &&...ranges) -> std::vector< result_of_t< XformT, meta::value_t< InputRangeTs >... > > |
Similar to clojure.core/into-array. More... | |
bool | state_wrapper_data_is_reduced (maybe_reduced_tag, bool is_reduced) |
template<typename T > | |
auto | reduced_if (T &&x, bool is_reduced) -> maybe_reduced< estd::decay_t< T > > |
Wraps x in a maybe_reduced , where is_reduced contains whether the reduction should actually finish. More... | |
template<typename T > | |
auto | reduced (T &&x) -> decltype(reduced_if(std::forward< T >(x), true)) |
Wraps x such that the reduction should finish. More... | |
template<typename T > | |
auto | not_reduced (T &&x) -> decltype(reduced_if(std::forward< T >(x), false)) |
Wraps x such that the reduction should continue. More... | |
ABL_METAFUNCTION_T (output_of) | |
ABL_METAFUNCTION_T (result_of) | |
template<typename ReducingFnT , typename StateT , typename... InputRangeTs> | |
auto | reduce (ReducingFnT &&step, StateT &&state, InputRangeTs &&...ranges) -> estd::decay_t< StateT > |
Similar to clojure.core/reduce. More... | |
template<typename ReducingFnT , typename StateT , typename... InputRangeTs> | |
auto | reduce_nested (ReducingFnT &&step, StateT &&state, InputRangeTs &&...ranges) -> decltype(detail::is_non_empty(ranges...) ?call(detail::reduce_nested_non_empty_flipped, std::forward< StateT >(state), std::forward< ReducingFnT >(step), std::forward< InputRangeTs >(ranges)...) :skip(std::forward< StateT >(state))) |
Similar to reduce, but does not unwrap reduced values. More... | |
template<typename ReducingFnT , typename InitialStateT , typename... InputTs> | |
auto | reductor (ReducingFnT &&step, InitialStateT &&state, InputTs &&...ins) -> reductor_fn< estd::decay_t< ReducingFnT >, estd::decay_t< InitialStateT >, estd::decay_t< InputTs >... > |
Constructs a reductor_fn object with deduced argument types. More... | |
template<typename... InputTs, typename ReducingFnT , typename InitialStateT > | |
auto | empty_reductor (ReducingFnT &&step, InitialStateT &&state) -> empty_reductor_fn< estd::decay_t< ReducingFnT >, estd::decay_t< InitialStateT >, estd::decay_t< InputTs >... > |
Constructs an empty_reductor_fn object with deduced argument types. More... | |
template<typename XformT , typename... InputRangeTs> | |
void | run (XformT &&xform, InputRangeTs &&...ranges) |
Runs a transducer composed with no significant reduction. More... | |
template<typename ValueT = detail::deduce_value_type, typename XformT , typename... RangeTs> | |
auto | sequence (XformT &&xform, const RangeTs &...ranges) -> sequence_range< typename boost::mpl::eval_if< std::is_same< ValueT, detail::deduce_value_type >, result_of< XformT, meta::value_t< RangeTs >... >, meta::identity< ValueT > >::type, estd::decay_t< XformT >, estd::decay_t< RangeTs >... > |
Factory for sequence_range values producing an iterable range out of a transducer, in the spirit of clojure.core/sequence$2. More... | |
template<typename ReducingFnT , typename StateT , typename... InputTs> | |
auto | skip (ReducingFnT &&, StateT &&state, InputTs &&...) -> skip_result_t< ReducingFnT, StateT, InputTs... > |
Skip calling the next reducing function in a transducer. More... | |
template<typename StateT > | |
auto | skip (StateT &&state) -> StateT && |
template<typename ReducingFnT , typename StateT , typename... InputTs> | |
auto | call (ReducingFnT &&step, StateT &&state, InputTs &&...ins) -> estd::enable_if_t< is_skip_state< estd::decay_t< StateT > > |
Call the next reducing function in a transducer that could otherwise skip calling the next reducing function. More... | |
template<typename T > | |
auto | state_complete (T &&s) -> decltype(state_traits_t< T >::complete(std::forward< T >(s))) |
Convenience function for calling state_traits::complete More... | |
template<typename T > | |
auto | state_is_reduced (T &&s) -> bool |
Convenience function for calling state_traits::is_reduced More... | |
template<typename T , typename D > | |
auto | state_data (T &&s, D &&d) -> decltype(state_traits_t< T >::data(std::forward< T >(s), std::forward< D >(d))) |
Convenience function for calling state_traits::data More... | |
template<typename T > | |
auto | state_unwrap (T &&s) -> decltype(state_traits_t< T >::unwrap(std::forward< T >(s))) |
Convenience function for calling state_traits::unwrap More... | |
template<typename T > | |
auto | state_unwrap_all (T &&s) -> decltype(state_traits_t< T >::unwrap_all(std::forward< T >(s))) |
Convenience function for calling state_traits::unwrap_all More... | |
template<typename T , typename U > | |
auto | state_rewrap (T &&s, U &&x) -> decltype(state_traits_t< T >::rewrap(std::forward< T >(s), std::forward< U >(x))) |
Convenience function for calling state_traits::unwrap_all More... | |
template<typename TagT = no_tag, typename StateT , typename DataT = TagT> | |
auto | wrap_state (StateT &&next, DataT &&data=DataT{}) -> state_wrapper< TagT, estd::decay_t< StateT >, estd::decay_t< DataT > > |
Given a tag TagT and a state next and associated data , returns a state_wrapper instance. More... | |
template<typename TagT , typename T > | |
auto | state_wrapper_complete (TagT, T &&s) -> decltype(state_complete(state_unwrap(std::forward< T >(s)))) |
Utility function for easy overloading of state_traits::complete for state wrappers with a specific tag. More... | |
template<typename TagT , typename T > | |
auto | state_wrapper_unwrap (TagT, T &&s) -> decltype(std::get< 0 >(std::forward< T >(s))) |
Utility function for easy overloading of state_traits::unwrap for state wrappers with a specific tag. More... | |
template<typename TagT , typename T > | |
auto | state_wrapper_unwrap_all (TagT, T &&s) -> decltype(state_unwrap_all(state_unwrap(std::forward< T >(s)))) |
Utility function for easy overloading of state_traits::unwrap_all for state wrappers with a specific tag. More... | |
template<typename TagT , typename T , typename U > | |
auto | state_wrapper_rewrap (TagT, T &&s, U &&x) -> decltype(wrap_state< TagT >( state_rewrap(state_unwrap(std::forward< T >(s)), x), state_wrapper_data(std::forward< T >(s)))) |
Utility function for easy overloading of state_traits::rewrap for state wrappers with a specific tag. More... | |
template<typename TagT , typename T , typename D > | |
auto | state_wrapper_data (TagT tag, T &&s, D &&) -> decltype(state_wrapper_data(tag, std::forward< T >(s))) |
Utility function for easy overloading of state_traits::data for state wrappers with a specific tag. More... | |
template<typename T > | |
auto | state_wrapper_data (T &&s) -> decltype(state_wrapper_data(typename estd::decay_t< T >::tag |
template<typename TagT , typename T > | |
auto | state_wrapper_data (TagT, T &&s) -> decltype(std::get< 1 >(std::forward< T >(s))) |
template<typename TagT , typename DataT > | |
bool | state_wrapper_data_is_reduced (TagT, DataT &&) |
Utility function that returns whether the DataT associated with a state wrapper with tag TagT is reduced – i.e. More... | |
template<typename TagT , typename T > | |
bool | state_wrapper_is_reduced (TagT tag, T &&s) |
Utility function for easy overloading of state_traits::is_reduced for state wrappers with a specific tag. More... | |
template<typename XformT , typename ReducingFnT , typename StateT , typename... InputRangeTs> | |
auto | transduce (XformT &&xform, ReducingFnT &&step, StateT &&state, InputRangeTs &&...ranges) -> estd::decay_t< StateT > |
Similar to clojure.core/transduce. More... | |
template<typename InputRangeT > | |
constexpr auto | chainr (InputRangeT &&r) -> chainr_t< estd::decay_t< InputRangeT > > |
Transducer produces the sequence passed as parameter after all other input has finished. More... | |
template<typename InputRangeT , typename... InputRangeTs> | |
constexpr auto | chainr (InputRangeT &&r, InputRangeTs &&...rs) -> decltype(comp(chainr(std::forward< InputRangeT >(r)), chainr(std::forward< InputRangeTs >(rs))...)) |
template<typename... InputRangeTs> | |
constexpr auto | chain (InputRangeTs &&...rs) -> decltype(chainr(std::forward< InputRangeTs >(rs)...)) |
Alias for chainr More... | |
template<typename InputRangeT > | |
constexpr auto | chainl (InputRangeT &&r) -> chainl_t< estd::decay_t< InputRangeT > > |
Transducer produces the sequence passed as parameter before processing the first input. More... | |
template<typename InputRangeT , typename... InputRangeTs> | |
constexpr auto | chainl (InputRangeT &&r, InputRangeTs &&...rs) -> decltype(comp(chainl(std::forward< InputRangeT >(r)), chainl(std::forward< InputRangeTs >(rs))...)) |
template<typename InitT = std::size_t, typename StepT = InitT> | |
constexpr auto | count (InitT init=InitT{0}, StepT step=StepT{1}) -> count_t< InitT, StepT > |
Generator transducer produces a sequence: More... | |
template<typename InputRangeT > | |
constexpr auto | cycle (InputRangeT &&r) -> cycle_t< estd::decay_t< InputRangeT > > |
Generator transducer produces the sequence passed as parameter, by cycling over it. More... | |
template<typename InputRangeT , typename... InputRangeTs> | |
constexpr auto | cycle (InputRangeT &&r, InputRangeTs &&...rs) -> decltype(comp(cycle(std::forward< InputRangeT >(r)), cycle(std::forward< InputRangeTs >(rs))...)) |
template<typename IntegralT > | |
auto | drop (IntegralT &&n) -> drop_t< estd::decay_t< IntegralT > > |
Similar to clojure.core/drop$1. More... | |
template<typename PredicateT > | |
auto | drop_while (PredicateT &&n) -> drop_while_t< estd::decay_t< PredicateT > > |
Similar to clojure.core/drop_while$1. More... | |
template<typename ActionT > | |
auto | each (ActionT &&action) -> each_t< estd::decay_t< ActionT > > |
Transducer that evaluates action on each input, forwarding the input down the original inputs down the transducer chain. More... | |
template<typename MappingT > | |
auto | eager (MappingT &&mapping) -> eager_t< estd::decay_t< MappingT > > |
Similar to clojure.core/eager-all$1. More... | |
template<typename IntegralT > | |
constexpr auto | enumerate_from (IntegralT &&init) -> enumerate_t< estd::decay_t< IntegralT > > |
Transducer that given a sequence: More... | |
template<typename PredicateT > | |
auto | filter (PredicateT &&predicate) -> filter_t< estd::decay_t< PredicateT > > |
Similar to clojure.core/filter$1. More... | |
template<typename... ValueTs> | |
constexpr auto | interpose (ValueTs &&...xs) -> interpose_t< estd::make_index_sequence< sizeof...(ValueTs)>, std::tuple< estd::decay_t< ValueTs >... > > |
Like clojure.core/interpose$1. More... | |
template<typename InputRangeT > | |
constexpr auto | iter (InputRangeT &&r) -> iter_t< estd::decay_t< InputRangeT > > |
Generator transducer produces the sequence passed as parameter, by iterating over it. More... | |
template<typename InputRangeT , typename... InputRangeTs> | |
constexpr auto | iter (InputRangeT &&r, InputRangeTs &&...rs) -> decltype(comp(iter(std::forward< InputRangeT >(r)), iter(std::forward< InputRangeTs >(rs))...)) |
template<typename MappingT > | |
auto | map (MappingT &&mapping) -> map_t< estd::decay_t< MappingT > > |
Similar to clojure.core/map$1. More... | |
template<typename MappingT > | |
constexpr auto | map_indexed (MappingT &&mapping) -> decltype(comp( count(), map(std::forward< MappingT >(mapping)))) |
Similar to clojure.core/map-indexed$1. More... | |
template<typename MappingT > | |
auto | mapcat (MappingT &&mapping) -> decltype(comp( cat, map(std::forward< MappingT >(mapping)))) |
Similar to clojure.core/mapcat$1. More... | |
template<typename IntegralT > | |
auto | partition (IntegralT &&n) -> partition_t< estd::decay_t< IntegralT > > |
Similar to clojure.core/partition-all$1. More... | |
template<typename MappingT > | |
auto | partition_by (MappingT &&mapping) -> partition_by_t< estd::decay_t< MappingT > > |
Similar to clojure.core/partition-by$1. More... | |
template<typename InputRangeT > | |
constexpr auto | product (InputRangeT &&r) -> product_t< estd::decay_t< InputRangeT > > |
Transducer combines every element that passes by with every element in the sequence that it takes as arguemnt. More... | |
template<typename InputRangeT1 , typename InputRangeT2 , typename... InputRangeTs> | |
constexpr auto | product (InputRangeT1 &&r1, InputRangeT2 &&r2, InputRangeTs &&...rs) -> decltype(comp(product(std::forward< InputRangeT1 >(r1)), product(std::forward< InputRangeT2 >(r2)), product(std::forward< InputRangeTs >(rs))...)) |
template<typename ProbabilityT , typename GeneratorT = detail::default_generator> | |
auto | random_sample (ProbabilityT prob, GeneratorT generator=GeneratorT{}) -> decltype(filter(detail::random_sampler< ProbabilityT, GeneratorT > |
Similar to clojure.core/random-sample$1. More... | |
template<typename StopT > | |
constexpr auto | range (StopT &&stop) -> decltype(comp( count(), take(std::forward< StopT >(stop)))) |
Generator transducer version of Python range More... | |
template<typename StartT , typename StopT > | |
constexpr auto | range (StartT &&start, StopT &&stop) -> decltype(comp( count(start), take(std::max(decltype(stop-start) |
template<typename StartT , typename StopT , typename StepT > | |
constexpr auto | range (StartT &&start, StopT &&stop, StepT &&step) -> decltype(comp( count(start, step), take(std::max(decltype((stop-start)/step) |
template<typename T , typename InputStreamT > | |
auto | read (InputStreamT &stream) -> read_t< T, std::reference_wrapper< InputStreamT > > |
Generator transducer that produces a sequence of values of type T read from the given stream using the operator >> . More... | |
template<typename T1 , typename T2 , typename... Ts, typename InputStreamT > | |
auto | read (InputStreamT &stream) -> decltype(comp(read< T1 >(stream), read< T2 >(stream), read< Ts >(stream)...)) |
template<std::size_t N, typename InputStreamT > | |
auto | readbuf (InputStreamT &stream) -> readbuf_t< std::reference_wrapper< InputStreamT >, std::array< char, N > > |
Generator transducer that reads buffers of size N from stream , and passes them into the sequence. More... | |
template<typename InputStreamT > | |
auto | readbuf (InputStreamT &stream, std::size_t n) -> readbuf_t< std::reference_wrapper< InputStreamT >, std::vector< char > > |
Like readbuf(stream) but with runtime specified size. More... | |
template<typename PredicateT > | |
auto | remove (PredicateT &&pred) -> decltype(filter(complement(std::forward< PredicateT >(pred)))) |
Similar to clojure.core/remove$1. More... | |
template<typename ValueT > | |
constexpr auto | repeat (ValueT &&r) -> repeat_t< estd::decay_t< ValueT > > |
Generator transducer produces the values passed as parameter infinitely. More... | |
template<typename ValueT , typename... ValueTs> | |
constexpr auto | repeat (ValueT &&r, ValueTs &&...rs) -> decltype(comp(repeat(std::forward< ValueT >(r)), repeat(std::forward< ValueTs >(rs))...)) |
template<typename IntegralT , typename... ValueTs> | |
constexpr auto | repeatn (IntegralT &&n, ValueTs &&...rs) -> decltype(comp(repeat(std::forward< ValueTs >(rs)...), take(std::forward< IntegralT >(n)))) |
Generator transducer produces the values passed as parameter up to n times. More... | |
template<typename TableT > | |
auto | replace (TableT &&table) -> decltype(map(detail::lookup_or_key< estd::decay_t< TableT > > |
Similar to clojure.core/replace$1. More... | |
template<typename TableT > | |
auto | replace_all (TableT &&table) -> decltype(map(detail::lookup_default< estd::decay_t< TableT > > |
Transducer that replaces all elements by table[tuplify(inputs)] More... | |
template<typename TableT > | |
auto | replace_all_safe (TableT &&table) -> decltype(map(detail::lookup_safe< estd::decay_t< TableT > > |
Transducer that replaces all elements by table.at(tuplify(inputs)) More... | |
template<typename ActionT > | |
auto | sink (ActionT &&action) -> sink_t< estd::decay_t< ActionT > > |
Transducer that evaluates action on each input. More... | |
template<typename IntegralT > | |
auto | take (IntegralT &&n) -> take_t< estd::decay_t< IntegralT > > |
Similar to clojure.core/take$1. More... | |
template<typename IntegralT > | |
auto | take_nth (IntegralT &&n) -> take_nth_t< estd::decay_t< IntegralT > > |
Similar to clojure.core/take_nth$1. More... | |
template<typename PredicateT > | |
auto | take_while (PredicateT &&p) -> take_while_t< estd::decay_t< PredicateT > > |
Similar to clojure.core/take_while$1. More... | |
auto | traced (std::string message) -> decltype(map(tracer |
Transducer that traces the values values that pass through it and forwards them forward in the chain. More... | |
template<typename OutputStreamT , typename InSeparatorT = detail::empty_output> | |
auto | write (OutputStreamT &stream, InSeparatorT in_sep=InSeparatorT{}) -> write_t< std::reference_wrapper< OutputStreamT >, InSeparatorT, InSeparatorT > |
Transducer that writes the into a given stream using the operator << . More... | |
template<typename OutputStreamT , typename InSeparatorT , typename ArgSeparatorT > | |
auto | write (OutputStreamT &stream, InSeparatorT in_sep, ArgSeparatorT arg_sep) -> write_t< std::reference_wrapper< OutputStreamT >, InSeparatorT, ArgSeparatorT > |
template<typename OutputStreamT > | |
auto | writebuf (OutputStreamT &stream) -> writebuf_t< std::reference_wrapper< OutputStreamT > > |
Generator transducer that reads buffers of size N from stream , and passes them into the sequence. More... | |
template<typename StateT , typename UnwrappedFn , typename WrappedFn > | |
auto | with_state (StateT &&st, UnwrappedFn &&, WrappedFn &&fn) -> meta::lazy_enable_if_t< !std::is_same< estd::decay_t< StateT >, estd::decay_t< decltype(state_complete(st))> >::value, std::result_of< WrappedFn(StateT)> > |
Given a value st that represents the state of a reduction, this function generically dispatches to the right function UnwrappedFn or WrappedFn , depending of whether the value is already wrapped or not. More... | |
Variables | |
constexpr struct atria::xform::emplace_back_rf_t | emplace_back_rf |
constexpr struct atria::xform::first_rf_t | first_rf |
constexpr struct atria::xform::last_rf_t | last_rf |
constexpr struct atria::xform::output_rf_t | output_rf |
skip_result_t< ReducingFnT, StateT, InputTs... > | |
constexpr auto | cat = cat_t {} |
Similar to clojure.core/cat$1. More... | |
constexpr dedupe_t | dedupe {} |
Equivalent to clojure/dedupe$0. More... | |
constexpr distinct_t | distinct {} |
Equivalent to clojure/distinct$0. More... | |
constexpr sorted_t | sorted {} |
Eager transducer that sorts the input sequence. More... | |
constexpr reversed_t | reversed {} |
Eager transducer that reverses the input sequence. More... | |
const enumerate_t< std::size_t > | enumerate |
Equivalent to enumerate_from(std::size_t{}) . More... | |
constexpr auto | interleave = interleave_t {} |
Similar to clojure.core/interleave$1. More... | |
stop | start { return ( comp( count(start), take(std::max(decltype(stop - start){}, stop - start))) ) |
stop start | step { return ( comp( count(start, step), take(std::max(decltype((stop - start) / step){}, (stop - start) / step))) ) |
constexpr auto | unzip = unzip_t {} |
Transducer that expands all tuples in the inputs in the argument list of the next transducer. More... | |
const map_t< tuplify_t > | zip |
Transducer that, if more than one argument is passed, forwards all of them as a single tuple. More... | |
Detailed Description
Efficient and flexible C++ implementation of transducers.
Transducers where first introduced in Clojure by Rich Hickie
Typedef Documentation
using maybe_reduced = state_wrapper<maybe_reduced_tag, T, bool> |
State wrapper for transducers that may want to signal that the reduction is finished.
- See also
- state_wrapper
- state_traits::reduced
Definition at line 48 of file maybe_reduced.hpp.
using transducer = transducer_impl< meta::unpack<detail::transducer_rf_gen, OutputT>, detail::transducer_function_t<InputT, OutputT> > |
Type erased transducer.
This allows to store transducers in places where the full type can not be known at compile time. The InputT
template argument is the type of the input over which you may apply the transducer. For example:
A second template argument can be passed to indicate the type of data after running through the transducer. By default, it's the same as the input.
Both the first or second template arguments can take a meta::pack<>
when it can take or pass more than one input type.
- Note
- Type erased transducers have a performance cost. Not only is it slower to pass them around, they are significantly slower when processing the sequence. For such, use them when really needed, and otherwise use
auto
and templates to avoid erasing the types of the transducers. - A type erased transducer actually defers applying the held transducer until it first runs through a sequence, as ilustrated by this example:
Definition at line 258 of file transducer.hpp.
Function Documentation
atria::xform::ABL_CONCEPT_SPEC | ( | State | ) |
Concept for a type that can be used as a state
of a reducing function.
By default, every type is a model of it. However, one might use this concept to check that a specialization of state_traits
is still valid.
Definition at line 42 of file concepts.hpp.
atria::xform::ABL_CONCEPT_SPEC | ( | Reducing_function | ) |
Concept for a function that can be used with reduce
for a specific state and inputs.
Definition at line 68 of file concepts.hpp.
atria::xform::ABL_CONCEPT_SPEC | ( | Transducer | ) |
Concept for a transducer
, this is, a function that takes a reducing function as an argument, and decorates it returning a new reducing function.
The second and third argument use the same rules the arguments to transducer
.
- See also
transducer
Definition at line 124 of file concepts.hpp.
atria::xform::ABL_CONCEPT_SPEC | ( | Transparent_transducer | ) |
Concept for a transducer that can be applied over any arguments.
Definition at line 150 of file concepts.hpp.
auto call | ( | ReducingFnT && | step, |
StateT && | state, | ||
InputTs &&... | ins | ||
) | -> estd::enable_if_t< is_skip_state<estd::decay_t<StateT> > |
Call the next reducing function in a transducer that could otherwise skip calling the next reducing function.
Returns the result of calling step(state, ins...)
wrapped in a type that can also hold plain state
values. If state is wrapped in such a type, it unwraps it before passing it.
- See also
- skip
constexpr auto atria::xform::chain | ( | InputRangeTs &&... | rs | ) | -> decltype( chainr(std::forward<InputRangeTs>(rs)...) ) |
constexpr auto atria::xform::chainl | ( | InputRangeT && | r | ) | -> chainl_t<estd::decay_t<InputRangeT> > |
constexpr auto atria::xform::chainr | ( | InputRangeT && | r | ) | -> chainr_t<estd::decay_t<InputRangeT> > |
constexpr auto atria::xform::count | ( | InitT | init = InitT{0} , |
StepT | step = StepT{1} |
||
) | -> count_t<InitT, StepT> |
constexpr auto atria::xform::cycle | ( | InputRangeT && | r | ) | -> cycle_t<estd::decay_t<InputRangeT> > |
auto atria::xform::drop | ( | IntegralT && | n | ) | -> drop_t<estd::decay_t<IntegralT> > |
auto atria::xform::drop_while | ( | PredicateT && | n | ) | -> drop_while_t<estd::decay_t<PredicateT> > |
Similar to clojure.core/drop_while$1.
Definition at line 82 of file drop_while.hpp.
auto atria::xform::each | ( | ActionT && | action | ) | -> each_t<estd::decay_t<ActionT> > |
auto atria::xform::eager | ( | MappingT && | mapping | ) | -> eager_t<estd::decay_t<MappingT> > |
auto atria::xform::empty_reductor | ( | ReducingFnT && | step, |
InitialStateT && | state | ||
) | -> empty_reductor_fn<estd::decay_t<ReducingFnT>, estd::decay_t<InitialStateT>, estd::decay_t<InputTs>... > |
Constructs an empty_reductor_fn
object with deduced argument types.
The InputTs
over which the reductor_fn functions have to be passed explicitly though.
Definition at line 250 of file reductor.hpp.
constexpr auto atria::xform::enumerate_from | ( | IntegralT && | init | ) | -> enumerate_t<estd::decay_t<IntegralT> > |
Transducer that given a sequence:
$$x_0, x_1, ..., x_n$$
produces a sequence
$$(init, x_0), (init+1, x_1), ..., (init+n, x_n)$$
It is inspired by Python's enumerate
generator.
Definition at line 102 of file enumerate.hpp.
auto atria::xform::filter | ( | PredicateT && | predicate | ) | -> filter_t<estd::decay_t<PredicateT> > |
Similar to clojure.core/filter$1.
Definition at line 82 of file filter.hpp.
constexpr auto atria::xform::interpose | ( | ValueTs &&... | xs | ) | -> interpose_t<estd::make_index_sequence<sizeof...(ValueTs)>, std::tuple<estd::decay_t<ValueTs>...> > |
Like clojure.core/interpose$1.
Definition at line 96 of file interpose.hpp.
auto atria::xform::into | ( | CollectionT && | col, |
XformT && | xform, | ||
InputRangeTs &&... | ranges | ||
) | -> CollectionT&& |
auto atria::xform::into_vector | ( | XformT && | xform, |
InputRangeTs &&... | ranges | ||
) | -> std::vector<result_of_t<XformT, meta::value_t<InputRangeTs>... > > |
Similar to clojure.core/into-array.
Definition at line 44 of file into_vector.hpp.
constexpr auto atria::xform::iter | ( | InputRangeT && | r | ) | -> iter_t<estd::decay_t<InputRangeT> > |
auto atria::xform::map | ( | MappingT && | mapping | ) | -> map_t<estd::decay_t<MappingT> > |
constexpr auto atria::xform::map_indexed | ( | MappingT && | mapping | ) | -> decltype( comp( count(), map(std::forward<MappingT>(mapping))) ) |
Similar to clojure.core/map-indexed$1.
Definition at line 40 of file map_indexed.hpp.
auto atria::xform::mapcat | ( | MappingT && | mapping | ) | -> decltype( comp( cat, map(std::forward<MappingT>(mapping))) ) |
Similar to clojure.core/mapcat$1.
Definition at line 40 of file mapcat.hpp.
auto atria::xform::not_reduced | ( | T && | x | ) | -> decltype( reduced_if(std::forward<T>(x), false) ) |
Wraps x such that the reduction should continue.
Definition at line 81 of file maybe_reduced.hpp.
auto atria::xform::partition | ( | IntegralT && | n | ) | -> partition_t<estd::decay_t<IntegralT> > |
Similar to clojure.core/partition-all$1.
Definition at line 114 of file partition.hpp.
auto atria::xform::partition_by | ( | MappingT && | mapping | ) | -> partition_by_t<estd::decay_t<MappingT> > |
Similar to clojure.core/partition-by$1.
Definition at line 117 of file partition_by.hpp.
constexpr auto atria::xform::product | ( | InputRangeT && | r | ) | -> product_t<estd::decay_t<InputRangeT> > |
Transducer combines every element that passes by with every element in the sequence that it takes as arguemnt.
Like itertools.product, from Python.
Definition at line 90 of file product.hpp.
auto atria::xform::random_sample | ( | ProbabilityT | prob, |
GeneratorT | generator = GeneratorT{} |
||
) | -> decltype( filter(detail::random_sampler<ProbabilityT, GeneratorT> |
Similar to clojure.core/random-sample$1.
Definition at line 74 of file random_sample.hpp.
auto atria::xform::read | ( | InputStreamT & | stream | ) | -> read_t<T, std::reference_wrapper<InputStreamT> > |
auto atria::xform::readbuf | ( | InputStreamT & | stream | ) | -> readbuf_t<std::reference_wrapper<InputStreamT>, std::array<char, N> > |
Generator transducer that reads buffers of size N
from stream
, and passes them into the sequence.
It passes them into the sequence as an range with char*
iterators.
Definition at line 89 of file readbuf.hpp.
auto atria::xform::readbuf | ( | InputStreamT & | stream, |
std::size_t | n | ||
) | -> readbuf_t<std::reference_wrapper<InputStreamT>, std::vector<char> > |
Like readbuf(stream)
but with runtime specified size.
Definition at line 99 of file readbuf.hpp.
auto atria::xform::reduce | ( | ReducingFnT && | step, |
StateT && | state, | ||
InputRangeTs &&... | ranges | ||
) | -> estd::decay_t<StateT> |
Similar to clojure.core/reduce.
Unlike std::accumulate
, this reduces over a range (doesn't take to distinct iterators) and can reduce over several ranges at the same time. It also supports early termination for transducers.
- Note
- 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:
One should instead:
Definition at line 70 of file reduce.hpp.
auto atria::xform::reduce_nested | ( | ReducingFnT && | step, |
StateT && | state, | ||
InputRangeTs &&... | ranges | ||
) | -> decltype( detail::is_non_empty(ranges...) ? call(detail::reduce_nested_non_empty_flipped, std::forward<StateT>(state), std::forward<ReducingFnT>(step), std::forward<InputRangeTs>(ranges)...) : skip(std::forward<StateT>(state)) ) |
Similar to reduce, but does not unwrap reduced
values.
This is useful when calling reduce recursively inside a transducer.
- See also
- take
Definition at line 63 of file reduce_nested.hpp.
auto atria::xform::reduced | ( | T && | x | ) | -> decltype( reduced_if(std::forward<T>(x), true) ) |
Wraps x such that the reduction should finish.
Definition at line 73 of file maybe_reduced.hpp.
auto atria::xform::reduced_if | ( | T && | x, |
bool | is_reduced | ||
) | -> maybe_reduced<estd::decay_t<T> > |
Wraps x in a maybe_reduced
, where is_reduced
contains whether the reduction should actually finish.
Definition at line 60 of file maybe_reduced.hpp.
auto atria::xform::reductor | ( | ReducingFnT && | step, |
InitialStateT && | state, | ||
InputTs &&... | ins | ||
) | -> reductor_fn<estd::decay_t<ReducingFnT>, estd::decay_t<InitialStateT>, estd::decay_t<InputTs>... > |
Constructs a reductor_fn
object with deduced argument types.
Definition at line 175 of file reductor.hpp.
auto atria::xform::remove | ( | PredicateT && | pred | ) | -> decltype( filter(complement(std::forward<PredicateT>(pred))) ) |
Similar to clojure.core/remove$1.
Definition at line 40 of file remove.hpp.
constexpr auto atria::xform::repeat | ( | ValueT && | r | ) | -> repeat_t<estd::decay_t<ValueT> > |
Generator transducer produces the values passed as parameter infinitely.
Definition at line 64 of file repeat.hpp.
constexpr auto atria::xform::repeatn | ( | IntegralT && | n, |
ValueTs &&... | rs | ||
) | -> decltype( comp(repeat(std::forward<ValueTs>(rs)...), take(std::forward<IntegralT>(n))) ) |
Generator transducer produces the values passed as parameter up to n
times.
Definition at line 82 of file repeat.hpp.
auto atria::xform::replace | ( | TableT && | table | ) | -> decltype( map(detail::lookup_or_key<estd::decay_t<TableT> > |
Similar to clojure.core/replace$1.
Definition at line 93 of file replace.hpp.
auto atria::xform::replace_all | ( | TableT && | table | ) | -> decltype( map(detail::lookup_default<estd::decay_t<TableT> > |
Transducer that replaces all elements by table[tuplify(inputs)]
Definition at line 101 of file replace.hpp.
auto atria::xform::replace_all_safe | ( | TableT && | table | ) | -> decltype( map(detail::lookup_safe<estd::decay_t<TableT> > |
Transducer that replaces all elements by table.at(tuplify(inputs))
Definition at line 109 of file replace.hpp.
void atria::xform::run | ( | XformT && | xform, |
InputRangeTs &&... | ranges | ||
) |
auto atria::xform::sequence | ( | XformT && | xform, |
const RangeTs &... | ranges | ||
) | -> sequence_range< typename boost::mpl::eval_if< std::is_same<ValueT, detail::deduce_value_type>, result_of<XformT, meta::value_t<RangeTs>...>, meta::identity<ValueT> >::type, estd::decay_t<XformT>, estd::decay_t<RangeTs>...> |
Factory for sequence_range
values producing an iterable range out of a transducer, in the spirit of clojure.core/sequence$2.
- See also
- sequence_range
Definition at line 268 of file sequence.hpp.
auto atria::xform::sink | ( | ActionT && | action | ) | -> sink_t<estd::decay_t<ActionT> > |
Transducer that evaluates action
on each input.
The input is forwarded into the action and discarded. The next transducer is excited for every input, but with no arguments.
- Note
- This is very similar to
each
, but can perform better since the arguments can be moved into the action. If we are not interested in the inputs after the action, this one should be preferred.
auto atria::xform::skip | ( | ReducingFnT && | , |
StateT && | state, | ||
InputTs && | ... | ||
) | -> skip_result_t<ReducingFnT, StateT, InputTs...> |
Skip calling the next reducing function in a transducer.
Returns the state parameter, potentially wrapped in a value convertible to/from whatever call would return for similar parameters.
A transducer might or might not call the next reducing function in the chain. One good example is filter, where if the predicate passes, it calls the next reducing function, otherwise it just returns the current state of the reduction. However, this poses the question: what should be the return type of such a transducer? The next reducing function might wrap the state in a state_wrapper to attach its own state to it. However, we don't know at this point what how to create such a wrapped value. This method, and call, take care of wrapping the state in a type that can hold values of both the current state, and the state that would be returned by the next reducing function. The metafunction skip_result defines such a type.
- See also
- call
- skip_result_t
- filter
- wrap_state
auto atria::xform::state_complete | ( | T && | s | ) | -> decltype( state_traits_t<T>::complete(std::forward<T>(s)) ) |
Convenience function for calling state_traits::complete
Definition at line 110 of file state_traits.hpp.
auto atria::xform::state_data | ( | T && | s, |
D && | d | ||
) | -> decltype( state_traits_t<T>::data(std::forward<T>(s), std::forward<D>(d)) ) |
Convenience function for calling state_traits::data
Definition at line 127 of file state_traits.hpp.
auto atria::xform::state_is_reduced | ( | T && | s | ) | -> bool |
Convenience function for calling state_traits::is_reduced
Definition at line 118 of file state_traits.hpp.
auto atria::xform::state_rewrap | ( | T && | s, |
U && | x | ||
) | -> decltype( state_traits_t<T>::rewrap(std::forward<T>(s), std::forward<U>(x)) ) |
Convenience function for calling state_traits::unwrap_all
Definition at line 152 of file state_traits.hpp.
auto atria::xform::state_unwrap | ( | T && | s | ) | -> decltype( state_traits_t<T>::unwrap(std::forward<T>(s)) ) |
Convenience function for calling state_traits::unwrap
Definition at line 136 of file state_traits.hpp.
auto atria::xform::state_unwrap_all | ( | T && | s | ) | -> decltype( state_traits_t<T>::unwrap_all(std::forward<T>(s)) ) |
Convenience function for calling state_traits::unwrap_all
Definition at line 144 of file state_traits.hpp.
auto atria::xform::state_wrapper_complete | ( | TagT | , |
T && | s | ||
) | -> decltype( state_complete(state_unwrap(std::forward<T>(s))) ) |
Utility function for easy overloading of state_traits::complete
for state wrappers with a specific tag.
- See also
- state_wrapper
- state_traits::complete
Definition at line 123 of file state_wrapper.hpp.
auto atria::xform::state_wrapper_data | ( | TagT | tag, |
T && | s, | ||
D && | |||
) | -> decltype( state_wrapper_data(tag, std::forward<T>(s)) ) |
Utility function for easy overloading of state_traits::data
for state wrappers with a specific tag.
- See also
- state_wrapper
- state_traits::data
Definition at line 173 of file state_wrapper.hpp.
bool atria::xform::state_wrapper_data_is_reduced | ( | TagT | , |
DataT && | |||
) |
Utility function that returns whether the DataT
associated with a state wrapper with tag TagT
is reduced – i.e.
idempotent. Can be overloaded custom tags.
- See also
- state_traits::reduced
Definition at line 195 of file state_wrapper.hpp.
bool atria::xform::state_wrapper_is_reduced | ( | TagT | tag, |
T && | s | ||
) |
Utility function for easy overloading of state_traits::is_reduced
for state wrappers with a specific tag.
Most of the time you may want to overload state_wrapper_is_reduced
instead.
- See also
- state_wrapper_data_is_reduced
- state_wrapper
- state_traits::is_reduced
Definition at line 210 of file state_wrapper.hpp.
auto atria::xform::state_wrapper_rewrap | ( | TagT | , |
T && | s, | ||
U && | x | ||
) | -> decltype( wrap_state<TagT>( state_rewrap(state_unwrap(std::forward<T>(s)), x), state_wrapper_data(std::forward<T>(s))) ) |
Utility function for easy overloading of state_traits::rewrap
for state wrappers with a specific tag.
- See also
- state_wrapper
- state_traits::rewrap
Definition at line 159 of file state_wrapper.hpp.
auto atria::xform::state_wrapper_unwrap | ( | TagT | , |
T && | s | ||
) | -> decltype( std::get<0>(std::forward<T>(s)) ) |
Utility function for easy overloading of state_traits::unwrap
for state wrappers with a specific tag.
- See also
- state_wrapper
- state_traits::unwrap
Definition at line 135 of file state_wrapper.hpp.
auto atria::xform::state_wrapper_unwrap_all | ( | TagT | , |
T && | s | ||
) | -> decltype( state_unwrap_all(state_unwrap(std::forward<T>(s))) ) |
Utility function for easy overloading of state_traits::unwrap_all
for state wrappers with a specific tag.
Definition at line 147 of file state_wrapper.hpp.
auto atria::xform::take | ( | IntegralT && | n | ) | -> take_t<estd::decay_t<IntegralT> > |
auto atria::xform::take_nth | ( | IntegralT && | n | ) | -> take_nth_t<estd::decay_t<IntegralT> > |
Similar to clojure.core/take_nth$1.
Definition at line 126 of file take_nth.hpp.
auto atria::xform::take_while | ( | PredicateT && | p | ) | -> take_while_t<estd::decay_t<PredicateT> > |
Similar to clojure.core/take_while$1.
Definition at line 72 of file take_while.hpp.
|
inline |
Transducer that traces the values values that pass through it and forwards them forward in the chain.
- See also
- trace
- tracer
Definition at line 41 of file traced.hpp.
auto atria::xform::transduce | ( | XformT && | xform, |
ReducingFnT && | step, | ||
StateT && | state, | ||
InputRangeTs &&... | ranges | ||
) | -> estd::decay_t<StateT> |
Similar to clojure.core/transduce.
Definition at line 41 of file transduce.hpp.
auto with_state | ( | StateT && | st, |
UnwrappedFn && | fn, | ||
WrappedFn && | fn | ||
) | -> meta::lazy_enable_if_t< !std::is_same< estd::decay_t<StateT>, estd::decay_t<decltype(state_complete(st))> >::value, std::result_of<WrappedFn(StateT)> > |
Given a value st
that represents the state of a reduction, this function generically dispatches to the right function UnwrappedFn
or WrappedFn
, depending of whether the value is already wrapped or not.
This is, during the first iteration of the reduction, UnwrappedFn
will be called, from then on, WrappedFnT
will be called.
The signatures should be of the form:
UnwrappedFn : A -> B
WrappedFn : B -> B
This function can dispatch both statically and dynamically in a transparent way. It is thus very useful for writing stateful transducers that can be type erased in a transducer<>
object.
- See also
- transducer
- take
Definition at line 58 of file with_state.hpp.
auto atria::xform::wrap_state | ( | StateT && | next, |
DataT && | data = DataT{} |
||
) | -> state_wrapper<TagT, estd::decay_t<StateT>, estd::decay_t<DataT> > |
Given a tag TagT
and a state next
and associated data
, returns a state_wrapper
instance.
- See also
- state_wrapper
Definition at line 104 of file state_wrapper.hpp.
auto atria::xform::write | ( | OutputStreamT & | stream, |
InSeparatorT | in_sep = InSeparatorT{} |
||
) | -> write_t<std::reference_wrapper<OutputStreamT>, InSeparatorT, InSeparatorT> |
auto atria::xform::writebuf | ( | OutputStreamT & | stream | ) | -> writebuf_t<std::reference_wrapper<OutputStreamT> > |
Generator transducer that reads buffers of size N
from stream
, and passes them into the sequence.
It passes them into the sequence as an range with char*
iterators.
Definition at line 79 of file writebuf.hpp.
Variable Documentation
constexpr dedupe_t dedupe {} |
Equivalent to clojure/dedupe$0.
Definition at line 88 of file dedupe.hpp.
constexpr distinct_t distinct {} |
Equivalent to clojure/distinct$0.
Definition at line 93 of file distinct.hpp.
const enumerate_t<std::size_t> enumerate |
Equivalent to enumerate_from(std::size_t{})
.
- Todo:
- Should be
constexpr
in C++14
constexpr auto interleave = interleave_t {} |
Similar to clojure.core/interleave$1.
Definition at line 77 of file interleave.hpp.
constexpr reversed_t reversed {} |
skip_result_t< ReducingFnT, StateT, InputTs... > |
constexpr sorted_t sorted {} |
constexpr auto unzip = unzip_t {} |