Is there a way to not have to initialize arrays twice?

In some cases, you can use std::mem::MaybeUninit:

use std::mem::MaybeUninit;

fn main() {
    let mut ys: MaybeUninit<[i32; 1000]> = MaybeUninit::uninit();
}

Removing the MaybeUninit wrapper via assume_init is unsafe because accessing uninitialized values is undefined behavior in Rust and the compiler can no longer guarantee that every value of ys will be initialized before it is read.

Your specific case is one of the examples in the MaybeUninit docs; read it for a discussion about the safety of this implementation:

use std::mem::{self, MaybeUninit};

fn foo(xs: &[i32; 1000]) {
    // I copied this code from Stack Overflow without
    // reading why it is or is not safe.
    let ys: [i32; 1000] = {
        let mut ys: [MaybeUninit<i32>; 1000] = unsafe { MaybeUninit::uninit().assume_init() };

        let mut xs = xs.into_iter();

        for y in &mut ys[..] {
            if let Some(x) = xs.next().copied() {
                *y = MaybeUninit::new(x / 3);
            }
        }

        unsafe { mem::transmute(ys) }
    };
    // ...
}

You cannot collect into an array, but if you had a Vec instead, you could do:

let ys: Vec<_> = xs.iter().map(|&x| x / 3).collect();

For your specific problem, you could also clone the incoming array and then mutate it:

let mut ys = xs.clone();
for y in ys.iter_mut() { *y = *y / 3 }

Leave a Comment