Reputation: 9220
I have several regular expressions that are defined at runtime and I would like to make them global variables.
To give you an idea, the following code works:
use regex::Regex; // 1.1.5
fn main() {
let RE = Regex::new(r"hello (\w+)!").unwrap();
let text = "hello bob!\nhello sue!\nhello world!\n";
for cap in RE.captures_iter(text) {
println!("your name is: {}", &cap[1]);
}
}
But I would like it to be something like this:
use regex::Regex; // 1.1.5
static RE: Regex = Regex::new(r"hello (\w+)!").unwrap();
fn main() {
let text = "hello bob!\nhello sue!\nhello world!\n";
for cap in RE.captures_iter(text) {
println!("your name is: {}", &cap[1]);
}
}
However, I get the following error:
error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
--> src/main.rs:3:20
|
3 | static RE: Regex = Regex::new(r"hello (\w+)!").unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
Does this mean that I need nightly Rust in order to make these variables global, or is there another way to do it?
Upvotes: 44
Views: 15658
Reputation: 9965
Since 1.80.0, you do not need any 3rd party crates - use the built-in std::sync::LazyLock. Note that only the static line has changed, the rest is identical to the question.
use regex::Regex;
use std::sync::LazyLock;
static RE: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"hello (\w+)!").unwrap());
// This code is identical to the question
fn main() {
let text = "hello bob!\nhello sue!\nhello world!\n";
for cap in RE.captures_iter(text) {
println!("your name is: {}", &cap[1]);
}
}
Upvotes: 9
Reputation: 12407
This is such a common pattern that there's a whole crate specifically for this use-case (with the added bonus of compile-time regex correctness checking): regex_static
.
static RE: Lazy<Regex> = regex_static::lazy_regex!("^Stack Overflo{1,50}w!$");
Upvotes: 1
Reputation: 33380
You can use the lazy_static macro like this:
use lazy_static::lazy_static; // 1.3.0
use regex::Regex; // 1.1.5
lazy_static! {
static ref RE: Regex = Regex::new(r"hello (\w+)!").unwrap();
}
fn main() {
let text = "hello bob!\nhello sue!\nhello world!\n";
for cap in RE.captures_iter(text) {
println!("your name is: {}", &cap[1]);
}
}
If you are using the 2015 edition of Rust, you can still use lazy_static
via:
#[macro_use]
extern crate lazy_static;
Upvotes: 48