Best way to compose iterator operations


#1

What’s the best way to get this code working:

fn main() {
        let v= vec![1,2,3,4,5,6,7,8,9];
        let mut vi = v.iter().filter(|i| **i>2);
        let cond = true;
        if cond {
            vi = vi.take(3);
        }
        let items = vi.collect::<Vec<&u32>>();
        println!("{:?}", items);
}

In this form it doesn’t compile because:

expected struct `std::iter::Filter`, found struct `std::iter::Take`

https://play.rust-lang.org/?gist=261f992adf079eb9e7636eccb19ae1f6&version=stable&mode=debug


#2

A few options:

extern crate either;

fn main() {
    {
        let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
        let cond = true;
        let count = if cond { 3 } else { std::usize::MAX };
        let vi = v.iter().filter(|&&i| i > 2).take(count);
        let items = vi.collect::<Vec<&u32>>();
        println!("{:?}", items);
    }
    {
        let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
        let cond = true;
        let vi = v.iter().filter(|&&i| i > 2);
        let items: Vec<&u32> = if cond {
            vi.take(3).collect()
        } else {
            vi.collect()
        };
        println!("{:?}", items);
    }
    {
        let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
        let cond = true;
        let vi = v.iter().filter(|&&i| i > 2);
        let vi = if cond {
            either::Either::Left(vi.take(3))
        } else {
            either::Either::Right(vi)
        };
        let items = vi.collect::<Vec<&u32>>();
        println!("{:?}", items);
    }
}

#3

Thanks. I’ve found another way with Box:

fn main() {
    let v= vec![1,2,3,4,5,6,7,8,9];
    let mut vi:Box<Iterator<Item=&u32>> = Box::new(v.iter().filter(|i| **i>2));
    let cond = true;
    if cond {
        vi = Box::new(vi.take(3));
    }
    let items = vi.collect::<Vec<&u32>>();
    println!("{:?}", items);
}

https://play.rust-lang.org/?gist=d4c8300bd57e55c40eae1d67f10d2ea0&version=stable&mode=debug


#4

Yes, Box works as well but you pay a perf penalty (whether it matters or not is a different question).