Iterating over vector of tuples and collecting

Hi, I am new to Rust (yet another), and have some trouble with iterators and collect() semantics :

I am trying to iterate over a Vect of Pairs of isize, and transform it in a Vect of Pairs of Pairs of isize and f32 (link to a playground with this code) :

type Point = (isize, isize); // (x,y)

fn work_on_tuples(tuples: &Vec<Point>){
    let moves : (&Point, f32) = tuples.iter()
        .map(|x : &Point| (x, 1.1 as f32))
        .collect();
}

Gives me the following compilation error :

error[E0277]: the trait bound `(&(isize, isize), f32): std::iter::FromIterator<(&(isize, isize), f32)>` is not satisfied
  --> src/main.rs:64:14
   |
64 |             .collect();
   |              ^^^^^^^ a collection of type `(&(isize, isize), f32)` cannot be built from an iterator over elements of type `(&(isize, isize), f32)`
   |
   = help: the trait `std::iter::FromIterator<(&(isize, isize), f32)>` is not implemented for `(&(isize, isize), f32)`

So here are the points I do not understand :

  • I do not understand this message : (&(isize, isize), f32)` cannot be built from an iterator over elements of type `(&(isize, isize), f32) : creating an X collection from an X iterator seems ok to me ?

  • I do not understand why would there be a problem creating a vector of tuples containing tuples references and float ?

Thank you for your help fellow rustaceans.

1 Like

Your main problem is that you are not collecting to a Vec<>:

type Point = (isize, isize);

fn work_on_tuples(tuples: &[Point]) {
    let moves: Vec<(&Point, f32)> =
        tuples
        .iter()
        .map(|t| (t, 1.1_f32))
        .collect();
}

fn main() {}

More:

  • It's more idiomatic to get a &[Point].
  • Numbers support suffixes, so there's no need to use "as f32". More in general, reduce as much as possible the number of times you use "as" in your Rust code because it's a sharp tool, it doesn't catch overflows, etc. Better to use X::from, or try_from where possible.
  • Are you sure you want to collect references of Points?
  • An alternative and different way to define your Point is "struct Point(isize, isize);" this allows nominal typing instead of structural typing.
2 Likes

Exactly thank you very much @leonardo,

Also thank you for your advises on best pratices, I'll go over the code and try to post a more idiomatic version as an exercise.

PS :
I was just seeing that BIG mistake while reading the doc of collect() that contains a clear example :

///
/// Basic usage:
///
/// ```
/// let a = [1, 2, 3];
///
/// let doubled: Vec<i32> = a.iter()
///                          .map(|&x| x * 2)
///                          .collect();
///
/// assert_eq!(vec![2, 4, 6], doubled);
/// ```