autofolder
autofolder provides a single-element "folding" container that can be used to accumulate/select/etc. values in an ad-hoc fashion.
TL;DR: DynFolder example
use *;
// Create an autofolder that retains the max u32 value:
let mut max = new;
// We can "fold-in" individual items:
max.fold;
// We can then peek at the running output:
println!;
// And still keep on folding by processing whole iterators:
max.extend;
// And finally consume the autofolder to get the final output value:
println!;
See also Min, Max and MinMax for useful specific reducers.
Rationale
Folding in Rust is accomplished via the Iterator::fold method, like so:
iterator.fold;
// (and this is all you can do)
That works well when all the data we need is provided by a single iterator. If we have a
more complex logic, fold can't be used.
autofolder flips this structure by being built with the initial value and the folding function, and accepting values from various types of different sources during its lifetime.
let mut autofolder = new;
// Fold in a whole iterator, can be repeated:
autofolder.extend;
// Fold in an individual value:
autofolder.fold;
Types of folders
By binding strategy
This crate provides two types of autofolders with different function binding strategies:
DynFolder: the folding function is provided as a closure that is kept in a struct field. Characteristics:- Folding function can use any type, builtin or otherwise.
- Each instance can use a different folding function, provided as a constructor argument.
On the flip side, we can't use
DynFolderwith.collect(). - Slightly less efficient than
ImplFolderdue to the use of dynamic dispatch - we are effectively using a function pointer instead of a function call, after all.
ImplFolder: the folding function is implemented via a trait.- Folding function can only use types defined in the user crate, which is a limitation of using traits.
- Each parameterized
ImplFolder, defined by the pair of types, can only have one folding function. Because of that, we can useImplFolderwith.collect()if theoutputtype implementsDefault - Slighly more efficient than
DynFolderdue to monomorphization, which turns.foldcalls into direct function calls.
By aggregation strategy
Reduce in rust is a special kind of folding where the aggregator and the item types of
the folding function are the same (Fn(Item, Item) -> Item). That allows us to set the
internal autofolder state with the first yielded value, without calling the corresponding
function.
This crate provides the following "autoreducer" types:
DynReduce: the reduce function is implemented via a trait.- Similar to
DynFolder. .into_inner()returns anOption.- Constructor takes the
reducefunction.
- Similar to
ImplReduce: the reduce function is implemented via a trait.- Similar to
ImplFolder. .into_inner()returns anOption.- Implements
.collect()even when the type parameters don't implementDefault.
- Similar to
Specific autofolders
This create also provides some built-in autofolders for specific functions:
Min: container that keeps only the minimal value iterated, as given bystd::cmp::PartialOrd.Max: analogous toMax, but for the max value.MinMax: container that keeps a tuple with both the min and max values.