composable 0.9.0

Easy composition of functional traits, functions or closures
Documentation
use super::*;

struct AddTo { 
    addend: usize,
}

impl Composable<usize,usize> for AddTo {
    fn apply(&self, input: usize) -> Result<usize> {
        Ok(input + self.addend)
    }
}

struct MultiplyBy { 
    factor: usize,
}

impl Composable<usize,usize> for MultiplyBy {
    fn apply(&self, input: usize) -> Result<usize> {
        Ok(input * self.factor)
    }
}

struct DivideBy {
    divisor: f64,
}

impl Composable<usize, f64> for DivideBy {
    fn apply(&self, input: usize) -> Result<f64> {
        if self.divisor == 0.0 {
            Err("division by zero".into())
        }
        else {
            Ok(input as f64 / self.divisor)
        }
    }
}


#[test]
fn test_compose() -> Result<()> {
    let a = AddTo { addend: 4 };
    let b = MultiplyBy { factor: 2 };
    let c = compose(a, b);
    let result = c.apply(1)?;
    assert_eq!(result, 10);
    Ok(())
}


#[test]
fn test_compose_method() -> Result<()> {
    let a = AddTo { addend: 4 };
    let b = MultiplyBy { factor: 2 };
    let c = a.compose(b);
    let result = c.apply(1)?;
    assert_eq!(result, 10);
    Ok(())
}


#[test]
fn test_composed() -> Result<()> {
    let a = AddTo { addend: 4 };
    let b = MultiplyBy { factor: 2 };
    let c = DivideBy { divisor: 2.0 };
    let d = composed![ a, b, c ];
    let result = d.apply(1)?;
    assert_eq!(result, 5.0);
    Ok(())
}



#[test]
fn test_error() -> Result<()> {
    let a = AddTo { addend: 4 };
    let b = DivideBy { divisor: 0.0 };
    let c = composed![ a, b ];
    let result = c.apply(1);
    assert!(result.is_err());
    Ok(())
}


#[test]
fn test_closure() -> Result<()> {
    let a = AddTo { addend: 4 };
    let b = |x: usize| Ok(x * x);
    let c = composed![ a, b ];
    let result = c.apply(1)?;
    assert_eq!(result, 25);
    Ok(())
}


#[test]
fn test_function() -> Result<()> {
    fn squared(x: usize) -> Result<usize> { Ok(x * x) }
    let a = AddTo { addend: 4 };    
    let b = MultiplyBy { factor: 2 };
    let c = composed![ a, squared, b ];
    let result = c.apply(1)?;
    assert_eq!(result, 50);
    Ok(())
}


struct AddToMsg { addend: usize }
 
impl Composable<usize, (usize, String)> for AddToMsg {
    fn apply(&self, input: usize) -> Result<(usize, String)> { Ok((input + self.addend, "hello".to_string())) }
}

#[test]
fn test_compose_t() -> Result<()> {
    let increment = AddToMsg { addend: 1 };
    let square = |x: usize| Ok(((x * x), "world".to_string()));
    let composition = compose_t(increment, square);
    let (result, (msg1, msg2)) = composition.apply(2)?;
    assert_eq!(result, 9);
    assert_eq!(msg1, "hello");
    assert_eq!(msg2, "world");
    Ok(())
}