Zach
Zach

Reputation: 5895

how to iterate a vector containing references?

Here is my code:

fn find_rects<'a >(
      rects: & Vec<&'a Rectangle>,  // reference of a vec containing Rectangle references
      width_limit: u32)
      ->  Vec<&'a Rectangle> // returns a vec of Rectangle references
{
    rects
        .iter()
        .filter(|x| x.width > width_limit)
        .collect()
}

It failed to compile. The error message says:

.collect()
 ^^^^^^^ value of type `Vec<&Rectangle>` cannot be built from `std::iter::Iterator<Item=&&Rectangle>`

And I found an answer to use .copied().collect() instead of .collect(). I tested and it works. But I don't know the reason.

Upvotes: 1

Views: 632

Answers (1)

BallpointBen
BallpointBen

Reputation: 13879

If my_vec: Vec<T>, then my_vec.iter() is an iterator over &T. But in this case T is &Rectangle so the iterator is over &&Rectangle, which is a distinct type from &Rectangle and so cannot be collected into a Vec<&Rectangle>.

iterator.copied() takes an iterator over &U and produces an iterator over U by copying (in the sense of Copy) each element (by dereferencing it; copied() is equivalent to iterator.map(|&x| x) and iterator.map(|x| *x)).

All that's left is to recognize that U is &Rectangle and that &U: Copy for any U, including when U is &Rectangle. So Iterator<Item=&&Rectangle>::copied() produces an iterator of &Rectangle, which can indeed be collected into a Vec<&Rectangle> (or, really, any FromIterator, of which Vec is just one).

Upvotes: 5

Related Questions