rustiterator

How to chain iterators dynamically?


I need to build repeating sequences of characters which have to look like

It can rather simply be coded for a given level with nested iterators:

fn level_n(next: impl Iterator<Item = char> + Clone) -> impl Iterator<Item = char> + Clone {
    repeat(once('x').chain(next))
        .take(10 as usize)
        .flat_map(|v| v)
}

And then:

level_n(level_n(level_n(level_0(2))))
    .cycle()
    .take(2000)
    .collect::<Vec<char>>();

Playground

But I can't figure out how to chain them dynamically for arbitrary n. This should look like:

let v = (0..3)
    .fold(level_0(3), |a, i| level_n(a))
    .cycle()
    .take(2000)
    .collect::<Vec<char>>();

It doesn't work because types are different, plus cycle requires its iterator to be Clone so can't keep it in a builder struct.

ps - here is a lame workaround by giving up on Clone and opting to collect/into_iter (iter.cloned didn't work either).


Solution

  • You could try emulating a Box<dyn Iterator<Item = char> + Clone> indirectly:

    trait CloneCharIter: Iterator<Item = char> {
        fn do_clone(&self) -> Box<dyn CloneCharIter>;
    }
    impl<T: Iterator<Item = char> + Clone + 'static> CloneCharIter for T {
        fn do_clone(&self) -> Box<dyn CloneCharIter> {
            Box::new(self.clone())
        }
    }
    impl Clone for Box<dyn CloneCharIter> {
        fn clone(&self) -> Self {
            self.as_ref().do_clone()
        }
    }
    
    fn level_0(p: usize) -> Box<dyn CloneCharIter> {
        Box::new(
            ['a', 'b', 'c', 'd']
                .into_iter()
                .flat_map(move |c| repeat(c).take(p)),
        )
    }
    
    fn level_n(next: Box<dyn CloneCharIter>) -> Box<dyn CloneCharIter> {
        Box::new(
            repeat(once('x').chain(next))
                .take(10 as usize)
                .flat_map(|v| v),
        )
    }
    
    let v = (0..3)
        .fold(level_0(3), |a, _| level_n(a))
        .cycle()
        .take(2000)
        .collect::<Vec<char>>();
    

    (playground)