首页 > 解决方案 > 为什么 `Regex::new` 的结果不能分配给常量?

问题描述

我有许多重复的常量,形式如下:

pub const FOO_REGEX: Regex = Regex::new(r"foo.*").unwrap();
pub const BAR_REGEX: Regex = Regex::new(r"bar.*").unwrap();

我想通过使用macro_rules!宏来简单地做到这一点。

我试过了:

macro_rules! pattern {
    ($value:literal) => {
        Regex::new($value).unwrap()
    }
}

pub const FOO_REGEX: Regex = pattern!(r"foo.*");

但是编译器抱怨:

error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
  --> lib.rs:7:9
   |
7  |         Regex::new($value).unwrap()
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
11 | pub const FOO_REGEX: Regex = pattern!(r"foo.*");
   |                              ------------------ in this macro invocation

根据本指南,我尝试了许多可用的指示符选项,例如expr, ident,但我仍然无法编译宏。

为什么literal指示符不适用于此宏表达式?

标签: rust

解决方案


这与宏无关:如果您直接编写代码(操场),则会得到相同的错误。这里的问题是调用Regex::new不是文字 (1) 并且不能在编译时进行评估 (还没有? )。您将需要使用类似lazy_staticcrate 的东西来确保Regex::new在运行时调用它来编译正则表达式:

use regex::Regex;
use lazy_static::lazy_static;

lazy_static!{
   pub static ref FOO_REGEX: Regex = Regex::new(r"foo.*").unwrap();
}

操场


(1)引用这个答案

文字是在代码中按原样true写入的值: , 1, "hello"; 表达式 [like Regex::new]的结果不能是文字(根据定义)。结果类型可能看起来相似(甚至相同),但类型在这里无关紧要。


推荐阅读