Why struct std::iter::Map doesn't constraint 'I' to be an Iterator?
Background
In Rust you can create an iterator by implementing 'Iterator' trait which requires you to implement a single method 'next(&mut self)'. We can then use 'map' to transform the elements emitted by the iterator. In the example below, I create an Iterator that emits 10 integers starting from a specified integer. I then map the iterator to a function that doubles every element.
pub struct IntIterator {
pub start: u32
}
impl Iterator for IntIterator {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
if self.start == 10 {
return None
}
self.start += 1;
return Some(self.start)
}
}
fn main(){
let it = IntIterator{start: 0};
let double: Vec<u32> = it.map(|x| x*2).collect();
println!("{:?}", double); // [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
}
How map is implemented?
The map function has no logic and simply returns a 'Map' object.
fn map<B, F>(self, f: F) -> Map<Self, F>
where
Self: Sized,
F: FnMut(Self::Item) -> B,
{
Map::new(self, f)
}
Lets look into the Map struct. Map has two fields, the iterator and the function. But note that the struct never forces the 'I' to be of type Iterator, neither does it say anything about F. This was not obvious to me when and probably will not be to most of the Rust beginners.
Not adding any restriction on the fields has many advantages. Say 'Map' was defined as below:-