Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Things on this page are fragmentary and immature notes/thoughts of the author. Please read with your own judgement!

Tips and Traps

  1. std::cell::OnceCell is a partial implementation of once_cell in the Rust standard library.

  2. There are 2 Rust crates lazy_static and once_cell for (lazy) once assignment (which can be used to create singletons). once_cell is preferred to lazy_static for a few reasons .

    • once_cell is both more flexible and more convenient than lazy_static .

    • Unlike once_cell , lazy_static supports spinlock-based implementation of blocking which works with #![no_std].

    • once_cell will likely be part of the Rust standard library in future.

  3. Once assignment means that you can only assign value to such a variable once. However, it is still possible to mutate the variable after initialization.

  4. When defining a static variable which implements Copy, you can define it as a static reference. This helps avoiding accidental implicity copies. The more idiomatic way is to define a wrapper non-Copy struct so that you can be sure that the underlying data won’t get copied.

:timing
:sccache 1
:dep once_cell = "1.13.0"
Timing: true sccache: true
Loading...
use std::{sync::Mutex, collections::HashMap};
use once_cell::sync::Lazy;
Loading...

Create a Mutable Static Variable (Singleton)

static GLOBAL_DATA_1: Lazy<Mutex<HashMap<i32, String>>> = Lazy::new(|| {
    let mut m = HashMap::new();
    m.insert(13, "Spica".to_string());
    m.insert(74, "Hoyten".to_string());
    Mutex::new(m)
});
Loading...
GLOBAL_DATA_1.lock().unwrap().insert(1, "New change".to_string());
GLOBAL_DATA_1.lock().unwrap().get(&1)
Some("New change")

Create a Immutable Static Variable (Singleton)

Mutex allows threads to mutate the static variable after initialization. It is not necessary if you just need a readable static variable (after initialization).

static GLOBAL_DATA_2: Lazy<HashMap<i32, String>> = Lazy::new(|| {
    let mut m = HashMap::new();
    m.insert(13, "Spica".to_string());
    m.insert(74, "Hoyten".to_string());
    m
});
Loading...
GLOBAL_DATA_2.insert(1, "New change".to_string());
GLOBAL_DATA_2.get(&1)
[E0596] Error: cannot borrow immutable static item `GLOBAL_DATA_2` as mutable
   [command_6:1:1]
   
 1 │ GLOBAL_DATA_2.insert(1, "New change".to_string());
   ·   
   ·                          cannot borrow as mutable
   · 
   · Note: You can change an existing variable to mutable like: `let mut x = x;`
───╯
GLOBAL_DATA_2.get(&13)
Some("Spica")
Loading...

Lazy Referencing Lazy

static GLOBAL_DATA_3: Lazy<[Lazy<&[usize]>; 2]> = Lazy::new(|| {
    let mut arr: [Lazy<&[usize]>; 2] = [
        Lazy::new(|| &[]),
        Lazy::new(|| &[]),
    ];
    arr[0] = Lazy::new(|| &[1, 2, 3]);
    arr[1] = Lazy::new(|| &[4, 5, 6, 7]);
    arr
});
Loading...
GLOBAL_DATA_3
Lazy { cell: OnceCell(Uninit), init: ".." }
Loading...
let x1: &[usize] = &GLOBAL_DATA_3[0];
x1
[1, 2, 3]
Loading...
let x2: &[usize] = &GLOBAL_DATA_3[1];
x2
[4, 5, 6, 7]
Loading...