Kompost
🚧🚧🚧🚧🚧 Under construction 🚧🚧🚧🚧🚧
A crate to ease functional programming in rust by facilitating the composability and re-usability of Iterator methods and anonymous Iterators—all without writing any trait or struct, without using macros or unsafe code.
Anonymous iterators
Adding a method to Iterator requires boilerplate in Rust—just have a look
at [src/anonymous.rs]:
- A Struct that holds a state (e.g., the parent iterator)
- A Constructor
- The implementation of
Iteratorfor the struct - A trait that defines the method
- A blanket implementation of that trait for all
Iterators.
This crate provides convenience by offering anonymous Iterators that are defined by two closures only.
As all Iterators, they are defined by their behavior during creation and in
the next method. The former is given by a closure that receives the current
[Iterator] and returns a context structure. The second closure
then computes the next value from the context and has mutable access to this context.
Hence, the anonymous() method strongly resembles Iterator::scan() with the notable
exception that the first parameter is a closure.
use *;
assert_eq!;
A slightly more complex idea is to collect the iterator first and define a custom behavior.
assert_eq!;
This enables more complex tasks. For instance, we can transpose a nested iterable
structure ([IntoIterator]<Item = [IntoIterator]<_>>) without the need of
writing a single struct or trait! The example is annotated with the inline type
hints as shown by rust-analyzer lsp:
let x: = // An array in row-major order
.chunks // Nested iterable: Chunks<i32>
.anonymous // AnonymousIterator
.flatten // impl Iterator<Item = &i32>
.copied // impl Iterator<Item = i32>
.collect;
assert_eq!;
This can be conveniently "bundled" in a function—transpose()
to be used with the composed() from this crate.
Composed iterators
Iterator composition allows defining reusable groups of frequently used combinations of [Iterator]
methods (such as map or scan) that can be easily tested.
A very simple example might look like:
use ComposedIterable;
assert_eq!
Kompost comes with a few useful (at least to me), predefined compound functions such as
transpose and periodic_windows().
The letter shows a few interesting aspects: How a compound function can accept an additional parameter,
how stricter type restrictions can be enforced (ExactSizeIterator), and a more advanced showcase
of the anonymous() method.
The compound function can then be easily applied:
let size=3;
let x = .into_iter
.composed
.flatten
.;
assert_eq!