Define non-constant static variables with lazy initialization
It’s no secret that initializing constants at compile time is a good practice in programming. Not only do you reduce the initialization overhead, but you also make it easier for the compiler to cleverly optimize your code by knowing the value of the constant in advance.
Sometimes, however, it’s impossible to initialize every constant at compile time since it requires performing non-constant operations or fetching data available only at runtime. For instance, say we make repetitive use of the number √7
in our program. Instead of calculating it every time, it would be better to define a constant for it like follows:
const ROOT_OF_SEVEN: f64 = 7_f64.sqrt();
This code, however, is invalid. The Rust compiler returns the following error:
cannot call non-const fn `f64::<impl f64>::sqrt` in constants
calls in constants are limited to constant functions, tuple structs and tuple variants
The same happens if we try to initialize a constant 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 can see, certain constants that would be useful to initialize at compile time require non-constant operations. This is where Rust’s lazy_static
crate comes in handy. lazy_static
allows you to define global static variables that get initialized lazily, meaning that their values only get set upon their first actual usage at runtime. Lazy statics only need to be initialized the first time they’re used and, since this is a one-time operation, their runtime initialization overhead is negligible.
In this article, we’ll take a look at how to use Rust’s lazy_static
crate to lazily initialize global constants and a few of their use cases.
Use lazy_static
To use the lazy_static
crate, you simply add it to your project dependencies by
This post originally appeared on TechToday.