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
pub struct SkipIterator<I: Iterator> {
  inner: I,
}

impl<I, T> Iterator for SkipIterator<I>
where
  I: Iterator<Item = T>,
{
  type Item = T;
  fn next(&mut self) -> Option<Self::Item> {
    self.inner.next()?; // if that returns None, return immediately with a None, use ? to do that job. If it returns a Some then also still an option - correct return type.
    self.inner.next() // Iterator is going skip half of iterations
  }
}

// in order to make this work on any other trait
// we're going to have to implement our own trait: `IterCombi`
// put that as a bound on the trait using the colon.
pub trait IterCombi: Iterator + Sized {
  // create ftn - will wrap Self
  fn skip_half(self) -> SkipIterator<Self> {
    SkipIterator { inner: self }
  }
}

// for everything that implements iterator and sized,
// it now implements intercombi as long as the trait itercombi is in scope while that's running
impl<I: Iterator + Sized> IterCombi for I {}

#[cfg(test)] // test module
mod test_skip {
  use super::*;
  #[test]
  fn test_skip_half() {
    let v: i32 = (0..10).skip_half().sum(); // syntactic sugar for creating a range iterator
    assert_eq!(v, 1 + 3 + 5 + 7 + 9);
  }
  #[test]
  fn test_step_by() {
    let v: i32 = (0..10).step_by(3).sum();
    assert_eq!(v, 0 + 3 + 6 + 9);
  }
  use itertools::Itertools;
  #[test]
  fn test_interleave() {
    let v: Vec<i32> = (0..4).interleave((11..15).rev()).collect();
    assert_eq!(v, vec![0, 14, 1, 13, 2, 12, 3, 11]);
  }

  #[test]
  // `cargo test intersperse` to just run that test in isolation
  fn test_intersperse() {
    let s = "hello world etc";
    let v: Vec<&str> = s.split(" ").intersperse(",").collect();
    assert_eq!(v, vec!["hello", ",", "world", ",", "etc"]);

    let s2 = s.split(" ").join(",");
    assert_eq!(s2, "hello,world,etc");
  }
}