I need to intialise a 16-byte array with a random value (not a Vec or a slice).
I'm currently using:
let mut rng = rand::thread_rng();
let mut foo = [0u8; 16];
rng.fill(&mut foo);
let foo = foo; // discard mutability
but this seems needlessly verbose, and writes the array twice (first, initialising with zeros, then, writing random values).
Can I initialise an array to a random value, rather than initialising it to zeros and updating it to a random value?
Two ways come to my mind.
rnd.gen()
directly. According to its documentation it can generate arrays with up to 32 elements directly. (Note that rand
has a feature called min_const_gen
that removes this restriction, but requires Rust 1.51
or newer. Which should be fine in almost all cases)[(); N]
(which is a zero-cost abstraction, as it is a zero-sized type) and .map()
it to its desired value. This can be done with arbitrarily large arrays.use rand::Rng;
fn main() {
let mut rng = rand::thread_rng();
let foo1: [u8; 16] = rng.gen();
let foo2: [u8; 16] = [(); 16].map(|()| rng.gen());
println!("{:?}", foo1);
println!("{:?}", foo2);
}
[202, 93, 254, 143, 106, 93, 194, 80, 141, 108, 119, 155, 125, 85, 84, 205]
[24, 237, 188, 0, 6, 240, 228, 117, 41, 253, 29, 148, 246, 47, 96, 181]
But be aware of the quote from Rng::gen()
's documentation:
For arrays of integers, especially for those with small element types (< 64 bit), it will likely be faster to instead use
Rng::fill
.
So while gen()
is technically more concise and only writes to the array once, it might also be less efficient. But if this is relevant for you, don't take my word and instead benchmark it yourself.