I am relying on iterators to perform some streaming processing. I have an issue where I have to store the result of a filter_map in a struct. For this purpose, I have used generics. You can have a minimal example of my issue in this playground. It seems that it cannot conclude that the result of my filter_map (the FilterMap struct) is a u32 iterator, even though .next() returns a Option<u32> as expected from a u32 iterator (let test: Option<u32> = new_iter.next(); does not make any compilation error).
As a temporary fix, I have stored the Iterator as a Box<Iterator<Item=u32>>, which works just fine. However, I am concerned about some sort of performance hit since I am relying on dynamic function dispatch on a pretty hot path.
Am I doing something wrong? What can I do to fix it? In my program, the iterator should stay in the struct but I am open to suggestions.
Return IteratorContainer<impl Iterator<Item = u32>> from new. This says, "I am returning an Iterator, but I'm not going to say exactly what type it is, just that it yields u32". This won't be a performance hit because the compiler knows what type it is, but you can't rely on anything beside it being an Iterator
@RustyYato I don't think that would work in this case.
struct IteratorContainer<I> {
iter: I,
}
impl<I> IteratorContainer<I> {
fn new<J: Iterator<Item=i16>>(iter: J) -> IteratorContainer<impl Iterator<Item=u32>> {
IteratorContainer {
iter: iter.filter_map(|it| if it < 0 { None } else { Some(it as u32) })
.skip(1),
}
}
}
fn main() {
let iterator = -2..4;
let container = IteratorContainer::new(iterator);
}
The compiler complains (correctly) that it can't figure out what I is.
error[E0282]: type annotations needed for `IteratorContainer<impl std::iter::Iterator>`
--> src/main.rs:22:21
|
22 | let container = IteratorContainer::new(iterator);
| --------- ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for `I`
| |
| consider giving `container` the explicit type `IteratorContainer<impl std::iter::Iterator>`, where the type parameter `I` is specified
error: aborting due to previous error
I think you'd need to make this a free function instead of an associated function of IteratorContainer<I>. That way you don't need to specify what I is.