Need help with vec iter with map

I'm trying to populate a vector with tuples using inter and map and then accessing the vector using another iter.

In this case pay no attention to the fact tuples are being used in this way since I'm simplifying code that is using window creations instead of tuples.

I'm not sure why, but the first iter seems to be failing to populate the vec with tuples.

Please advise.
Code:

fn create_tuple1() -> (f64, f64) {
    (5.0, 6.0)
}

fn create_tuple2() -> (f64, f64) {
    (8.0, 9.0)
}

fn main() {
    let mut multi_tuples: Vec<_> = (0..2 as usize)
        .into_iter()
        .map(|n| {
            match n {
                0 => create_tuple1(),
                1 => create_tuple2(),
                _ => {}
            };
        })
        .collect();

    loop {
        let mut x = false;
        for (i, tuple) in multi_tuples.iter_mut().enumerate() {
            match i {
                0 => {
                    println!("Tuple number = {}", i);
                    println!("Tuple = {:?}", tuple);
                }
                1 => {
                    println!("Tuple number = {}", i);
                }
                _ => {}
            }
        }
        if !x {
            break;
        }
    }
}

Error is:

  Compiling playground v0.0.1 (/playground)
error[E0308]: `match` arms have incompatible types
  --> src/main.rs:16:22
   |
13 | /             match n {
14 | |                 0 => create_tuple1(),
   | |                      --------------- this is found to be of type `(f64, f64)`
15 | |                 1 => create_tuple2(),
   | |                      --------------- this is found to be of type `(f64, f64)`
16 | |                 _ => {}
   | |                      ^^ expected tuple, found `()`
17 | |             };
   | |_____________- `match` arms have incompatible types
   |
   = note:  expected tuple `(f64, f64)`
           found unit type `()`

Ok, I replaced the first iter code with (and it worked):

        let mut multi_tuples: Vec<(f64, f64)> = vec![];
        multi_tuples.push(create_tuple1());
        multi_tuples.push(create_tuple2());

but I'd still like to know why this iter didn't work and if there is a way to make it work the way I want:

     let mut multi_tuples: Vec<_> = (0..2 as usize)
         .into_iter()
         .map(|n| {
             match n {
                 0 => create_tuple1(),
                 1 => create_tuple2(),
                 _ => {}
             };
         })
         .collect();

map requires the same value for all arms of match. Use filter_map instead and either return Some(tuple) or None

If you know that every value in the Vec is either 0 or 1, you can use something that panics. Like:

     let mut multi_tuples: Vec<_> = (0..2 as usize)
         .into_iter()
         .map(|n| {
             match n {
                 0 => create_tuple1(),
                 1 => create_tuple2(),
                 _ => unreachable!()
             };
         })
         .collect();
1 Like

Just in case this wasn’t clear already:

If this is just for initialization, you can call the create_tuple*() functions in the vec! macro expression:

let mut multi_tuples: Vec<(f64, f64)> = vec![create_tuple1(), create_tuple2()];

Thank You for the clarity!!

Could you please give me a code example?

Sure. This should work

let mut multi_tuples: Vec<_> = (0..2 as usize)
         .into_iter()
         .filter_map(|n| {
             match n {
                 0 => Some(create_tuple1()),
                 1 => Some(create_tuple2()),
                 _ => None
             };
         })
         .collect();

Thank You! Super educational!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.