How to return a Iterator from a method?

I have the following code, how can I return a Iterator from the compute method?

pub trait BasicVec {
    fn compute(&self, part: u32) -> Box<Iterator<Item=i32>>;
}

pub struct ParaVec<'a> {
    name: &'static str,
    data: &'a Vec<i32>,
}

impl<'a> BasicVec for ParaVec<'a> {
    fn compute(&self, part: u32) -> Box<Iterator<Item=i32>> { // error
        Box::new(self.data.iter())
    }
}

I know the compiler can not infer enough information about self.data.iter(), but how can I give more hint to the compiler? and is there any way to express the return iterator in a generic way, such as if the data is Vec<T> ?

1 Like

There are 2 things to fix there. First, self.data.iter() is an iterator over &i32 rather than i32. We can change this to self.data.iter().cloned() to fix that. Second, a Box<Iterator<Item = i32>> implies a 'static lifetime for the iterator, where in this case the lifetime is limited. The most straightforward way to deal with that is to add a lifetime annotation to compute

pub trait BasicVec {
    fn compute<'a>(&'a self, part: u32) -> Box<Iterator<Item=i32> + 'a>;
}

pub struct ParaVec<'a> {
    name: &'static str,
    data: &'a Vec<i32>,
}

impl<'a> BasicVec for ParaVec<'a> {
    fn compute<'b>(&'b self, part: u32) -> Box<Iterator<Item=i32>+ 'b> {
        Box::new(self.data.iter().cloned())
    }
}
4 Likes

Thanks, as you pointed out, I need to use the cloned() method, so I change to the following ways to avoid the clone.


pub trait BasicVec {
    fn compute<'a>(&'a self, part: u32) -> Box<Iterator<Item=&i32> + 'a>;
}

pub struct ParaVec<'a> {
    name: &'static str,
    data: &'a Vec<i32>,
}

impl<'a> BasicVec for ParaVec<'a> {
    fn compute<'b>(&'b self, part: u32) -> Box<Iterator<Item=&i32>+ 'b> {
        Box::new(self.data.iter())
    }
}

That works too, but is there a reason you want to avoid calling cloned()? Turning an &i32 into a i32 is not an expensive operation.

I want the data structure to be generic later, the data to be Vec<T>.