If I generate 10 random numbers this way, it works (it produces different values)
fn main() {
let seed = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.expect("system time cannot be before unix epoch")
.as_millis() as u64;
let mut rng = oorandom::Rand32::new(seed);
for _ in 0..10 {
println!("Your random number is: {}", &rng.rand_range(0..4));
}
But if I factor them into a struct, the generated values are always the same:
use oorandom::{self, Rand32};
struct Util {
rng: Rand32,
}
impl Util {
pub fn new() -> Self {
let seed = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_millis() as u64;
println!("new color util {}", seed);
let rng = Rand32::new(seed);
Util { rng }
}
pub fn get_random(&self) -> u32 {
let mut rng = self.rng;
let random_number = rng.rand_range(0..4);
random_number
}
}
fn main() {
let util = Util::new();
for _ in 0..10 {
println!("Your random number is: {}", util.get_random());
}
}
What is the difference between those two ways to use the get_random
API, and why does it break when I put rng
in a struct?
This doesn't work because you are copying rng
out of the struct, then mutating it (registering that you have sampled a number):
impl Util {
pub fn get_random(&self) -> u32 {
let mut rng = self.rng; // <-- here you copy `rng`,
// creating a new value, unrelated with `self.rng`
let random_number = rng.rand_range(0..4); // <-- here you mutate `rng`,
random_number // but leave `self.rng` untouched
}
}
Instead, you must take a mutable borrow to self
to be able to mutate rng
in place:
impl Util {
pub fn get_random(&mut self) -> u32 {
// +++ `mut` has been added, to allow mutation of `self`
let rng = &mut self.rng; // this does not copy `self.rng`
let random_number = rng.rand_range(0..4);
random_number
}
}
Or, more shortly
impl Util {
pub fn get_random(&mut self) -> u32 {
let random_number = self.rng.rand_range(0..4);
random_number
}
}
Or even
impl Util {
pub fn get_random(&mut self) -> u32 {
self.rng.rand_range(0..4)
}
}