In this code, I build up an iterator by chaining multiple iterators together in a loop.
The problem is that the type of the resultant iterator changes depending on the number of iterations of the outer loop, and thus I cannot return it using an opaque type impl Iterator<Item=usize>
use std::iter;
fn returns_an_iter(base : usize) -> impl Iterator<Item=usize> {
(base..base+3).into_iter()
}
fn returns_chained_iter() -> impl Iterator<Item=usize> {
let mut result_iter = iter::empty::<usize>();
for i in 0..3 {
result_iter = result_iter.chain(returns_an_iter(i));
}
result_iter
}
fn main() {
for i in returns_chained_iter() {
println!("{}", i);
}
}
Is there a way around this other than to box each sub-iterator?
As you probably already guessed, this can't be done with a loop that reassigns the same variable because each chain is a different type (std::iter::Empty, Chain<Empty, std::slice::Iter<'_, usize>>, Chain<Chain<Empty, Iter<'_, usize>>, Iter<'_, usize>> and so on).
You can do this with a combination of trait magic, const generics, recursion, and specialization, but that's going to be a lot more complex than just boxing every time.
You can also collect all of the iterators into a vector instead of building up a chain:
fn returns_chained_iter() -> impl Iterator<Item=usize> {
let mut iters = vec![];
for i in 0..3 {
iters.push(returns_an_iter(i));
}
iters.into_iter().flatten()
}