1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
pub mod vector {
    pub fn init<T>(capacity: usize, f: fn(usize) -> T) -> Vec<T> {
        let mut v = Vec::with_capacity(capacity);
        for i in 0..capacity {
            v.push(f(i));
        }
        v
    }

    pub fn zip_with<T, U, V>(mut first: Vec<T>, mut second: Vec<U>, with: fn(T, U) -> V) -> Vec<V> {
        if first.len() != second.len() {
            panic!("You need to have equal lists");
        }

        let length = first.len();
        let mut v = Vec::with_capacity(length);
        for _ in 0..length {
            let x = first.drain(0..1).next().unwrap();
            let y = second.drain(0..1).next().unwrap();
            v.push(with(x, y));
        }
        v
    }

    pub fn zip<T, U>(first: Vec<T>, second: Vec<U>) -> Vec<(T, U)> {
        zip_with(first, second, |x, y| (x, y))
    }
}

pub mod truth {
    // or something that implements iter
    pub fn all<'a, T>(elems: &'a Vec<T>, f: fn(&'a T) -> bool) -> bool {
        elems.iter().fold(true, |acc, x| acc && f(x))
    }

    pub fn any<'a, T>(elems: &'a Vec<T>, f: fn(&'a T) -> bool) -> bool {
        elems.iter().fold(false, |acc, x| acc || f(x))
    }
}

pub mod futures {
    #[macro_export]
    macro_rules! pipe {
        ($init:tt $(=>$fn:ident)+) => {{
            let mut r = $init;
            $( r = $fn(r).await; )*
            r
        }}
    }
}

#[cfg(test)]
mod tests {

    use super::*;
    #[test]
    fn test_vec_init() {
        let v = vector::init(4, |x| x.pow(2));
        assert_eq!(v[0], 0);
        assert_eq!(v[1], 1);
        assert_eq!(v[2], 4);
        assert_eq!(v[3], 9);

        println!("{:?}", v);
    }

    #[test]
    fn test_zip_with() {
        let xs = vec![1, 2, 3];
        let ys = vec![4, 5, 6];

        assert_eq!(vector::zip_with(xs, ys, |x, y| x + y), vec![5, 7, 9]);
    }

    #[test]
    fn test_zip() {
        let xs = vec![1, 2, 3];
        let ys = vec![4, 5, 6];

        let zs = vector::zip(xs, ys);
        println!("{:?}", zs);

        assert_eq!(zs[0], (1, 4));
        assert_eq!(zs[1], (2, 5));
        assert_eq!(zs[2], (3, 6));
    }

    #[test]
    fn test_all() {
        let xs = vec![1, 3, 5, 7, 9];
        let is_odd = |x| x % 2 != 0;

        assert_eq!(truth::all(&xs, is_odd), true)
    }

    #[test]
    fn test_any() {
        let xs = vec![1, 4, 5, 7, 9];
        let is_even = |x| x % 2 == 0;

        assert_eq!(truth::any(&xs, is_even), true)
    }

    async fn double(x: i32) -> i32 {
        x + x
    }
    async fn square(x: i32) -> i32 {
        x * x
    }

    #[tokio::test]
    async fn test_piping() {
        let x = pipe!(2
            => double
            => square
            => double
            => square);

        assert_eq!(x, 1024);
    }
}