Lazy_static! inside a function's scope

Hello,
While going through the docs for GitHub - rust-lang/regex: An implementation of regular expressions for Rust. This implementation uses finite automata and guarantees linear time matching on all inputs., I found this code snippet:

use regex::Regex;

fn some_helper_function(text: &str) -> bool {
    lazy_static! {
        static ref RE: Regex = Regex::new("...").unwrap();
    }
    RE.is_match(text)
}

What is the benefit to having the lazy_static! inside the helper function, as opposed to the top level of the module? (I would guess that having a lazy_static! inside the helper function's scope would make RE unavailable to other functions in the module.)

If RE is going to be reused in a loop inside the helper function, couldn't we skip the lazy_static! and get an instance of a compiled regex to reuse with just a let? Or is it that the static instance RE will be magically preserved between different times when some_helper_function is called? (This doesn't sit very well with me because it seems to imply a side effect that is preserved beyond the scope of the helper function.)

What is the recommended pattern for defining these lazy-initialized statics? Should the lazy_static! be at the top level of the module versus inside the function where the values are used?

Thank you!

2 Likes

A static inside a function is exactly the same as having it outside of a function, it just limits the scope in which it can be accessed. Keeping statics/consts in the smallest scope of use keeps larger scopes clean (if no other function needs RE there isn't a real reason to put it outside of some_helper_function.)

Using lazy_static like this does the following:

  • Creates a static variable RE that can only be accessed inside some_helper_function.
  • On first access to RE (which happens to be the first execution of the function,) RE is created.
  • On future accesses/calls to some_helper_function, the calculated RE is used.

This is all the same as it would be if the lazy_static block was outside of the function. If you did a let re = Regex::new("...").unwrap(); in the function instead, it'd be calculated every time the function was run.

6 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.