Idiomatic way to write this code:

#1
  1. I understand why this code does not work:

pub struct Foo {}

pub struct Bar {}

pub struct Thing {
    foo: Foo,
    bar: Bar
}

pub fn mov_and_combine(f: Vec<Foo>, b: Vec<Bar>) -> Vec<Thing> {
    assert_eq!(f.len(), b.len());
    let n = f.len();
    let ans = Vec::new();

    for i in 0..n {
        ans.push(Thing { foo: f[i], bar: b[i] })
    }

    ans
}


the problem is that I am asking Rustc to move values out of the vector, but I’m passing them by referenc3e.

  1. There are a number of ways to resolve this – but none of them look elegant.

  2. Is there an idiomatic way to solve this problem? A vec of Foo and a vec of Bar goes in, a vec of Thing comes out, combining the two.

Thanks!

#2

Note: I don’t want to add Default, Copy, or Clone traits.

#3
pub struct Foo {}

pub struct Bar {}

pub struct Thing {
    foo: Foo,
    bar: Bar
}

pub fn mov_and_combine(f: Vec<Foo>, b: Vec<Bar>) -> Vec<Thing> {
    assert_eq!(f.len(), b.len());
    let n = f.len();
    let mut ans = Vec::new();

    let mut fi = f.into_iter();
    let mut bi = b.into_iter();

    for i in 0..n {
        ans.push(Thing { foo: fi.next().unwrap(), bar: bi.next().unwrap() })
    }

    ans
}

Is that the best we ca ndo?

#4
f.into_iter().zip(b)
    .map(...)
    .collect()

Iterator is your friend :slight_smile:

8 Likes