Define non-constant static variables with lazy initialization

It’s no secret that initializing constants at compile time is a superb practice in programming. Not only do you reduce the initialization overhead, but you furthermore mght make it easier for the compiler to cleverly optimize your code by knowing the worth of the constant upfront.
Sometimes, nonetheless, it’s unattainable to initialize every constant at compile time because it requires performing non-constant operations or fetching data available only at runtime. As an example, say we make repetitive use of the number √7
in our program. As a substitute of calculating it each time, it will be higher to define a relentless for it like follows:
const ROOT_OF_SEVEN: f64 = 7_f64.sqrt();
This code, nonetheless, is invalid. The Rust compiler returns the next error:
cannot call non-const fn `f64::::sqrt` in constants
calls in constants are limited to constant functions, tuple structs and tuple variants
The identical happens if we attempt to initialize a relentless with an environment variable:
const LANG: String = env::var("LANG").unwrap();
From the Rust compiler:
cannot call non-const fn `std::env::var::<&str>` in constants
calls in constants are limited to constant functions, tuple structs and tuple variants
As you may see, certain constants that may be useful to initialize at compile time require non-constant operations. That is where Rust’s lazy_static
crate is useful. lazy_static
lets you define global static variables that get initialized lazily, meaning that their values only get set upon their very first usage at runtime. Lazy statics only should be initialized the primary time they’re used and, since it is a one-time operation, their runtime initialization overhead is negligible.
In this text, we’ll take a have a look at how one can use Rust’s lazy_static
crate to lazily initialize global constants and a couple of of their use cases.
Use lazy_static
To make use of the lazy_static
crate, you just add it to your project dependencies by