I pretty new to Rust and I’m wondering why global mutables are hard?
At first glance you can just use static variable of a type supporting interior mutability - RefCell, Mutex, etc…
At first glance you can just use static variable of a type supporting interior mutability - RefCell, Mutex, etc…
They're not.
fn main() {
unsafe {
COUNTER += 1;
println!("COUNTER = {}", COUNTER);
}
unsafe {
COUNTER += 10;
println!("COUNTER = {}", COUNTER);
}
}
Global mutable variables are as easy in Rust as in any other language. Unlike other languages, Rust also provides better things that you can use instead. use std::sync::Mutex;
static LIST: Mutex<Vec<String>> = Mutex::new(Vec::new());
fn main() -> Result<(), Box<dyn std::error::Error>> {
LIST.lock()?.push("hello world".to_string());
println!("{}", LIST.lock()?[0]);
Ok(())
}It doesn't increment anything for starters. The example would be more convoluted if it did the same thing.
And strings in rust always delivers the WTFs I need o na Friday:
"hello world".to_string() use std::sync::Mutex;
fn main() -> Result<(), Box<dyn std::error::Error>> {
static PEDANTRY: Mutex<u64> = Mutex::new(0);
*PEDANTRY.lock()? += 1;
println!("{}", PEDANTRY.lock()?);
Ok(())
}And declaring a static variable inside a function, even if in main, smells.
static mut COUNTER: u32 = 0;
(at top-level)If on 2024 edition, you will additionally need
#![allow(static_mut_refs)]And that’s where a number of people blow a gasket.
Since 1.80 the vast majority of uses are a LazyLock away.