Return Iterator over self.vec

I am very new to Rust and already blown away by its beauty and.. "simplificity " :b

I am writing a struct to store a matrix. The struct has a vector of vectors and k, l for dimensions.

struct Matrix {
mat : Vec<Vec< i32>>,
k : usize ,
l : usize,
}

I want to implement a method which returns an Iterator over the Elements over a row.

fn getRow(&self, k : usize)-> Box<Iterator<Item = i32>>{
Box::new(self.mat[k].iter())
}

As I vaguely understood, I cannot return an Iterator, so I boxed it.
However I get the following error messages

error[E0271]: type mismatch resolving <std::slice::Iter<'_, i32> as std::iter::Iterator>::Item == i32
--> src/main.rs:44:9
|
44 | Box::new(self.mat[k].iter())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected reference, found i32
|
= note: expected type &i32
found type i32
= note: required for the cast to the object type dyn std::iter::Iterator<Item=i32>

I was speculating, that it has to do with lifetimes. However the introduction of a generalized lifetime 't does not help me very much

You can, if you use the impl Trait feature. The lifetime part comes in there because Vec::iter() returns references to the underlying elements, but your signature was claiming the iterator returns i32 (but due to references, it's actually returning &i32). Along the same lines, the returned iterator is keeping a borrow over the Vec, which in turns keeps the borrow over self (your Matrix). You need to indicate this in the signature. All that summed up looks like this:

fn get_row<'a>(&'a self, k: usize) -> impl Iterator<Item = i32> + 'a {
    self.mat[k].iter().cloned()
}

Note we stick a cloned() call - that clones each element as it traverses, yielding an owned value (i32, rather than &i32). We're still borrowing the vec (iterators are lazy, and don't do anything until you traverse them), so we indicate the lifetime relationship between borrowing self and the returned iterator.

3 Likes

self.mat[k].iter() returns an iterator of references (Item=&i32), but you try to return iterator of values (Item=i32). Simply adding .cloned() would fix that. Also, you need to add an explicit lifetime annotation to the trait inside the Box, because the default is 'static and won't work for us.

Playground

Actually, you can :slight_smile: Either by using the "impl Trait" feature or explicitly naming the type.

Also, try to post a link to playground with some runnable code, it'd make it easier for others to help!

1 Like