rust-lang-nursery / lazy-static.rs

A small macro for defining lazy evaluated static variables in Rust.
Apache License 2.0
1.9k stars 111 forks source link

Support initialization with manual value? #160

Open intgr opened 4 years ago

intgr commented 4 years ago

I have a use case that's similar to lazy_static but that cannot be solved nicely right now.

If the default initializer to a lazy_static variable is something that wants arguments at initialization-time, or is something that can fail, then currently the usage is very awkward. Of course it's possible that I'm missing something obvious, I'm very new to Rust still, so apologies in advance if that's the case.

You may well consider this out of scope for this project (wouldn't really be "lazy"), but I wanted to ask before I contemplate if it's worth forking the project.

Basically, what I want would look something like this:

lazy_static! {
    pub static ref QUOTES: QuoteLibrary;
}
fn main() {
    let filename = "quotes.yaml";
    match QuoteLibrary::load_file(filename) {
        //                        ^^^^^^^^
        // allows me to provide arguments to the initializer function
        Ok(quotes) => lazy_static::initialize(&QUOTES, quotes); // assigned here
        Err(err) => // allows reporting initialization failures nicely
    }
}

The semantics would be:

This saves me from writing:

lazy_static! {
    static ref QUOTES: Mutex<Option<QuoteLibrary>> = Mutex::new(None);
}

and also saves .lock().unwrap() calls every time I want to use the QUOTES value.

For context, this is what I initially wrote, when attempting to use the current lazy_static:

lazy_static! {
    pub static ref QUOTES: QuoteLibrary = QuoteLibrary::load_file_or_exit("quotes.yaml");
    //              Note: cannot supply arguments from main() function.   ^^^^^^^^^^^^^
}
fn main() {
    lazy_static::initialize(&QUOTES);
    // other code
}
impl QuoteLibrary {
    pub fn load_file_or_exit(filename: &str) -> QuoteLibrary {
        match Self::load_file(filename) {
            Ok(quotes) => quotes,
            Err(err) => {
                println!("Error loading {}: {}", filename, err);
                exit(1);   // <-- Calling exit() from an initializer is awkward
            }
        }
    }
}
pravic commented 4 years ago

Check this for your case: https://docs.rs/once_cell/1.4.0/once_cell/