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
use std::iter::IntoIterator;

use tea_dtype::IsNone;

pub trait TIterator: Iterator + DoubleEndedIterator {}
impl<I: Iterator + DoubleEndedIterator> TIterator for I {}

pub trait IterBasic: IntoIterator + Sized {
    #[inline]
    fn vfold<U, F>(self, init: U, mut f: F) -> U
    where
        F: FnMut(U, Self::Item) -> U,
        Self::Item: IsNone,
    {
        self.into_iter()
            .fold(init, |acc, v| if v.not_none() { f(acc, v) } else { acc })
    }

    #[inline]
    fn vfold2<U, I2, F>(self, other: I2, init: U, mut f: F) -> U
    where
        I2: IntoIterator,
        I2::Item: IsNone,
        F: FnMut(U, Self::Item, I2::Item) -> U,
        Self::Item: IsNone,
    {
        self.into_iter().zip(other).fold(init, |acc, (va, vb)| {
            if va.not_none() && vb.not_none() {
                f(acc, va, vb)
            } else {
                acc
            }
        })
    }

    #[inline]
    fn vfold_n<U, F>(self, init: U, mut f: F) -> (usize, U)
    where
        F: FnMut(U, <Self::Item as IsNone>::Inner) -> U,
        Self::Item: IsNone,
    {
        let mut n = 0;
        let acc = self.into_iter().fold(init, |acc, v| {
            if v.not_none() {
                n += 1;
                f(acc, v.unwrap())
            } else {
                acc
            }
        });
        (n, acc)
    }

    #[inline]
    fn vapply<F>(self, mut f: F)
    where
        F: FnMut(<Self::Item as IsNone>::Inner),
        Self::Item: IsNone,
    {
        self.into_iter().fold((), |(), v| {
            if v.not_none() {
                f(v.unwrap())
            }
        })
    }

    #[inline]
    fn vapply_n<F>(self, mut f: F) -> usize
    where
        F: FnMut(<Self::Item as IsNone>::Inner),
        Self::Item: IsNone,
    {
        let mut n = 0;
        self.into_iter().fold((), |(), v| {
            if v.not_none() {
                n += 1;
                f(v.unwrap())
            }
        });
        n
    }
}

impl<I: IntoIterator + Sized> IterBasic for I {}