How to replace lazy_static with the new OnceCell in Rust 1.70?

50 points ynn38

According to the release note of Rust 1.70, OnceCell struct is introduced as

Crates such as lazy_static and once_cell have filled this need in the past, but now these building blocks are part of the standard library, ported from once_cell's unsync and sync modules.

But how can I replace lazy_static with OnceCell? I have no idea because the example shown in the official documentation isn't related to global variables.

I have this lazy_static code (playground):

use std::collections::HashMap;

use lazy_static::lazy_static;

lazy_static! {
    static ref MEM: HashMap<usize, usize> = {
        let mut m = HashMap::new();
        m.insert(0, 0);
        m.insert(1, 1);
        m.insert(2, 2);
        m.insert(3, 6);
        m.insert(4, 24);
        m
    };
}

fn factorial(i: usize) -> usize {
    MEM[&i]
}

fn main() {
    println!("{}", factorial(0)); //=> 0
    println!("{}", factorial(1)); //=> 1
    println!("{}", factorial(2)); //=> 2
    println!("{}", factorial(3)); //=> 6
    println!("{}", factorial(4)); //=> 24
}

And I rewrote this code instead to use OnceCell, which panics as MEM is not yet initialized (though I explicitly call MEM.set()) (playground):

use std::{cell::OnceCell, collections::HashMap};

const MEM: OnceCell<HashMap<usize, usize>> = OnceCell::new();

fn factorial(i: usize) -> usize {
    MEM.get().unwrap()[&i]
}

fn main() {
    let mut m = HashMap::new();
    m.insert(0, 0);
    m.insert(1, 1);
    m.insert(2, 2);
    m.insert(3, 6);
    m.insert(4, 24);

    MEM.set(m).unwrap();

    println!("{}", factorial(0));
    println!("{}", factorial(1));
    println!("{}", factorial(2));
    println!("{}", factorial(3));
    println!("{}", factorial(4));
}

By the way, the nightly-only LazyCell worked like a charm (playground):

#![feature(lazy_cell)]

use std::{cell::LazyCell, collections::HashMap};

const MEM: LazyCell<HashMap<usize, usize>> = LazyCell::new(|| {
    let mut m = HashMap::new();
    m.insert(0, 0);
    m.insert(1, 1);
    m.insert(2, 2);
    m.insert(3, 6);
    m.insert(4, 24);
    m
});

fn factorial(i: usize) -> usize {
    MEM[&i]
}

fn main() {
    println!("{}", factorial(0));
    println!("{}", factorial(1));
    println!("{}", factorial(2));
    println!("{}", factorial(3));
    println!("{}", factorial(4));
}