#![warn(missing_docs)]
#![feature(fn_traits, unboxed_closures)]
pub use compose::{compose, compose_trans};
pub use transform::{Filtering, Identity, Mapping};
mod compose;
mod transform;
pub trait Transducer<'t, R, T, U> {
type Step: Fn(R, U) -> R + 't;
fn apply<Step: Fn(R, T) -> R + 't>(&self, step: Step) -> Self::Step;
}
pub fn reduce_iter<'t, R, T, U, I: Iterator<Item = U>,
Fold: Fn(R, T) -> R + 't,
Trans: Transducer<'t, R, T, U>>
(iter: I, seed: R, fold: Fold, trans: Trans) -> R
where Trans::Step: 't {
let step = trans.apply(fold);
let mut state = seed;
for t in iter {
state = step(state, t);
}
state
}
#[test]
fn reduce_iter_sum() {
let items = [2, 3, 5, 7, 11, 13, 17, 19];
let sum = reduce_iter(items.iter(), 0, |a, x| a + x, Identity::new());
assert_eq!(sum, 77);
}
pub fn transduce<'t, 'i, T: 't, U, I: Iterator<Item = U>,
Step: Fn(Vec<T>, U) -> Vec<T>,
Trans: Transducer<'t, Vec<T>, T, U, Step = Step>>
(iter: &'i mut I, trans: Trans)
-> Vec<T> where Trans::Step: 't {
fn append<TT>(mut r: Vec<TT>, t: TT) -> Vec<TT> { r.push(t); r }
let step = trans.apply(append);
let (min_sz, _) = iter.size_hint();
let mut state = Vec::with_capacity(min_sz);
for t in iter {
state = step(state, t);
}
state
}
#[test]
fn identity_is_identity_on_iter() {
let v = vec!(2i32, 3, 5, 7, 11);
let w = transduce(&mut v.clone().into_iter(), Identity::new());
assert_eq!(v, w);
}
#[test]
fn mapping_on_iter() {
let u = vec!(2i32, 3, 5, 7, 11);
let v = u.clone();
let f = |x: &i32| *x * 2;
let g = |x: i32| x * 2;
let m = Mapping::new(&f);
let n = Mapping::new(&g);
let w = transduce(&mut u.iter(), m);
let x = transduce(&mut v.into_iter(), n);
assert_eq!(w, vec!(4i32, 6, 10, 14, 22));
assert_eq!(w, x);
}
#[test]
fn filtering_on_iter() {
let p = |x: &i32| *x % 2 == 0;
let q = |x: &i32| *x % 3 != 0;
let f = Filtering::new(&p);
let h = Filtering::new(&q);
let v = vec!(2i32, 3, 5, 6, 7, 11);
let w = transduce(&mut v.iter().cloned(), f);
let x = transduce(&mut v.iter().cloned(), h);
assert_eq!(w, vec!(2i32, 6));
assert_eq!(x, vec!(2i32, 5, 7, 11));
}
#[test]
fn compose_mapping_filtering() {
let f = |x: i32| x * 2;
let p = |x: &i32| *x % 4 != 0;
let t = compose_trans(Mapping::new(&f), Filtering::new(&p));
let v = vec!(2i32, 3, 4, 5, 6, 7, 11);
let w = transduce(&mut v.into_iter(), t);
assert_eq!(w, vec!(6i32, 10, 14, 22));
}