4 ms·
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
by ekropotin 10mo ago
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…
- written-beyond 10mo agoI don't think it's specifically hard, it's more related to how it probably needed more plumbing in the language that authors thought would add to much baggage and let the community solve it. Like the whole async runtime debates
- School-Cotton 10mo ago> I pretty new to Rust and I’m wondering why global mutables are hard? 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.
- raggi 10mo agoPeople always complain about unsafe, so I prefer to just show the safe version. 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(()) }
- hu3 10mo agoThis is completely different from the previous example. 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()
- raggi 10mo agouse 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(()) }
- hu3 10mo agoStill different. Yours only increments once. Doesn't pass basic QA. And declaring a static variable inside a function, even if in main, smells.
- raggi 10mo agoOP you keep comparing to doesn't even declare the variable. I'm done with you.
- School-Cotton 10mo agoOP here, not showing how to declare the variable was an oversight on my part. static mut COUNTER: u32 = 0; (at top-level) If on 2024 edition, you will additionally need #![allow(static_mut_refs)]
- raggi 10mo agoYup, your example was fine, as I said I just wanted to show a safe method too :-)
- masklinn 10mo agoThat is correct. Kinda. Refcell can not work because Rust considers globals to be shared by multiple threads so requires thread safety. And that’s where a number of people blow a gasket.
- masklinn 10mo agoA second component is that statics require const initializers, so for most of rust’s history if you wanted a non-trivial global it was either a lot of faffing about or using third party packages (lazy_static, once_cell). Since 1.80 the vast majority of uses are a LazyLock away.