宏是否可以将标识符转为小写?

Phi*_*ord 12 macros rust

是否可以从字符串生成 Rust 宏中的符号或标识符?或者对标识符执行类似字符串的操作?

我想生成一个给定符号的方法,但需要将其小写以获取方法名称。

get!(B);

// should expand to

fn b() -> B {
    // method body
}
Run Code Online (Sandbox Code Playgroud)

很容易接近...

macro_rules! get {
    ($kind:ident, $method:ident)
        =>
    {
        fn $method() -> $kind {
           // method body
        }
    }
}

get!(B, b)
Run Code Online (Sandbox Code Playgroud)

但是很不满意。

sta*_*cks 10

我刚刚写了一个程序宏(casey)来做到这一点。

#![feature(proc_macro_hygiene)]

use casey::lower;

lower!(B); // would render as `b`

Run Code Online (Sandbox Code Playgroud)

更新

proc_macro_hygiene 从 rust 1.45.0 开始稳定,所以不再需要每晚。

  • 这样的事情让我脸上露出灿烂的笑容。感谢您的出色工作,我的业务逻辑源文件之一从 2k+ 行增加到了 400 行左右。你能告诉我我有多高兴吗? (2认同)

Bry*_*nry 9

前面的答案都是正确的;标准声明性宏无法做到这一点,您可以改为使用过程宏。然而,程序宏的一个更简单的替代方案(特别是如果像我一样,这是您尚未深入研究的语言领域)是 dtolnay 的Paste crate

这些文档中的一个示例:

use paste::paste;

paste! {
    // Defines a const called `QRST`.
    const [<Q R S T>]: &str = "success!";
}

fn main() {
    assert_eq!(
        paste! { [<Q R S T>].len() },
        8,
    );
}
Run Code Online (Sandbox Code Playgroud)

还支持大小写转换,例如[<ld_ $reg:lower _expr>]


lje*_*drz 3

不,没有一个宏可以对标识符执行这种字符串操作。

可以在编译器中创建这样的宏,但这似乎不是一个普遍的需求;今天只有实验性的concat_idents!东西接近这个(即标识符的类似字符串的操作)。

您的解决方法是目前唯一可用的解决方案。