Rust
Iterator adapter
Write your own type that implements Iterator.
Final task: iterator adapter
Write your own iterator adapter: CiftAdim, which yields the elements of any iterator skipping every other one. The adapter wraps the inner iterator and, in next, pulls two elements from it and returns the first:
struct CiftAdim<I> {
ic: I,
}
impl<I: Iterator> Iterator for CiftAdim<I> {
type Item = I::Item;
fn next(&mut self) -> Option<I::Item> {
let x = self.ic.next();
self.ic.next(); // skip one
x
}
}
Extension trait
To chain it as .cift_adim(), an extension trait is written and implemented generically for all iterators:
trait CiftAdimExt: Iterator + Sized {
fn cift_adim(self) -> CiftAdim<Self> {
CiftAdim { ic: self }
}
}
impl<I: Iterator> CiftAdimExt for I {}
let v: Vec<i32> = (1..=7).cift_adim().collect(); // [1, 3, 5, 7]
The standard library's step_by(2) does the same job; this task shows how adapters are built.
Exercise Your own adapter
Write the CiftAdim structure above, its Iterator implementation and the CiftAdimExt extension trait. Collect (1..=7).cift_adim() into a vector and "abcdef".chars().cift_adim() into a String, and print them separated by a space.
Show example solution
struct CiftAdim<I> {
ic: I,
}
impl<I: Iterator> Iterator for CiftAdim<I> {
type Item = I::Item;
fn next(&mut self) -> Option<I::Item> {
let x = self.ic.next();
self.ic.next();
x
}
}
trait CiftAdimExt: Iterator + Sized {
fn cift_adim(self) -> CiftAdim<Self> {
CiftAdim { ic: self }
}
}
impl<I: Iterator> CiftAdimExt for I {}
fn main() {
let v: Vec<i32> = (1..=7).cift_adim().collect();
let s: String = "abcdef".chars().cift_adim().collect();
println!("{:?} {}", v, s);
}
Test yourself
-
What does <code>type Item = I::Item;</code> mean?
- Item is always i32
- I is an element type
- It doesn't compile
- The adapter produces elements of the same type as the inner iterator
Show answer
The adapter produces elements of the same type as the inner iterator — I::Item is the associated type in I's Iterator implementation; the adapter passes it through unchanged.
-
Blanket implementation
impl<I: ____> CiftAdimExt for I {}
Show answer
impl<I: Iterator> CiftAdimExt for I {}
-
Input and cift_adim result
- 1..=7
- [1, 3, 5, 7]
- "abcdef".chars()
- "ace"
- 1..=2
- [1]
- empty iterator
- []
Next lesson: JSON config reader