Iterator adapter
- Rust course
- Intermediate
- Lesson 114/115
- 7 min
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.
Practice 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.
Starter code
fn main() {
// buraya yaz
}Sample 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);
}Expected output
[1, 3, 5, 7] ace
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 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 Correct answer
Explanation: I::Item is the associated type in I's Iterator implementation; the adapter passes it through unchanged.
2 Blanket implementation
impl<I: ____> CiftAdimExt for I {}
impl<I: Iterator> CiftAdimExt for I {}
Explanation: All iterators gain the extension trait.
3 Input and cift_adim result
| Term | Meaning |
|---|---|
1..=7 |
[1, 3, 5, 7] |
"abcdef".chars() |
"ace" |
1..=2 |
[1] |
empty iterator |
[] |