Reputation: 91
Today I did some tests on the nightly module std::lazy
. It works well in local variable. However, when I defined a const
variable, it gave me two different values. Seems the Colsure is called multiple times.
#![feature(once_cell)]
use rand::Rng; // 0.8.4
use std::lazy::Lazy;
const CONST_LAZY: Lazy<i32> = Lazy::new(|| rand::thread_rng().gen::<i32>());
fn main() {
let local_lazy: Lazy<i32> = Lazy::new(|| rand::thread_rng().gen::<i32>());
println!("{}", *local_lazy); // -1475423855
println!("{}", *local_lazy); // -1475423855
println!("{}", *CONST_LAZY); // 1975106939
println!("{}", *CONST_LAZY); // -1848043613
}
Upvotes: 8
Views: 382
Reputation: 42492
This is my code, can anyone tell me why?
Because you're confusing const
and static
.
Per the official documentation:
A constant item is an optionally named constant value which is not associated with a specific memory location in the program. Constants are essentially inlined wherever they are used, meaning that they are copied directly into the relevant context when used. This includes usage of constants from external crates, and non-
Copy
types. References to the same constant are not necessarily guaranteed to refer to the same memory address.
(note that the phrasing of the last sentence indicates consts could be promoted to statics and share a memory address, but there's no guarantee there, and while statics can be inlined it probably should not be observable through safe rust so should mostly be irrelevant).
In essence, your snippet is semantically equivalent to:
#![feature(once_cell)]
use rand::Rng; // 0.8.4
use std::lazy::Lazy;
fn main() {
let local_lazy: Lazy<i32> = Lazy::new(|| rand::thread_rng().gen::<i32>());
println!("{}", *local_lazy);
println!("{}", *local_lazy);
println!("{}", *Lazy::new(|| rand::thread_rng().gen::<i32>()));
println!("{}", *Lazy::new(|| rand::thread_rng().gen::<i32>()));
}
That is also why it compiles at all, as Lazy
is not thread-safe, and thus an actual global (a static
) will not compile as it could be shared between threads.
Upvotes: 10