In this code, A
does not need to be static mut
, but the compiler forces B
to be static mut
:
use std::collections::HashMap;
use std::iter::FromIterator;
static A: [u32; 21] = [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
];
static mut B: Option<HashMap<u32, String>> = None;
fn init_tables() {
let hm = HashMap::<u32, String>::from_iter(A.iter().map(|&i| (i, (i + 10u32).to_string())));
unsafe {
B = Some(hm);
}
}
fn main() {
init_tables();
println!("{:?} len: {}", A, A.len());
unsafe {
println!("{:?}", B);
}
}
This is the only way I have found to get close to what I actually want: a global, immutable HashMap
to be used by several functions, without littering all my code with unsafe
blocks.
I know that a global variable is a bad idea for multi-threaded applications, but mine is single threaded, so why should I pay the price for an eventuality which will never arise?
Since I use rustc
directly and not cargo
, I don't want the "help" of extern crates like lazy_static
. I tried to decypher what the macro in that package does, but to no end.
I also tried to write this with thread_local()
and a RefCell
but I had trouble using A
to initialize B
with that version.
In more general terms, the question could be "How to get stuff into the initvars section of a program in Rust?"
If you can show me how to initialize B
directly (without a function like init_tables()
), your answer is probably right.
If a function like init_tables()
is inevitable, is there a trick like an accessor function to reduce the unsafe
litter in my program?