macros - 宏可以扩展为模式组合吗?

标签 macros pattern-matching rust

从 Rust 1.0 开始,无法将多个模式组合到一个绑定(bind)中:

// It does not compile
match x as char {
    b @ ('A' | 'Z') => println!("A or Z: {}", b),
    _ => println!("Try again")
}

// Correct version
match x as char {
    b @ 'A' | b @ 'Z' => println!("A or Z: {}", b),
    _ => println!("Try again")
}

我想知道宏是否可以完成绑定(bind)所有不同可能性的肮脏工作。这是部分尝试:

macro_rules! bind_alternatives {
    ($x:ident, $e:expr) => ($x @ $e);
    ($x:ident, $e1:expr, $e2:expr) => (
        $x @ $e1 | $x @ $e2
    );
}

fn main() {
    let x = 'a';

    match x {
        bind_alternatives!(z, 'a', 'c') => println!("Matched"),
        _ => println!("No luck")
    };
}

这不编译:

example.rs:4:18: 4:19 error: macro expansion ignores token `|` and any following
example.rs:4         $x @ $e1 | $x @ $e2
                                      ^
example.rs:12:9: 12:40 note: caused by the macro expansion here; the usage of `bind_alternatives` is likely invalid in this context
example.rs:12         bind_alternatives!(z, 'a', 'c') => println!("Matched"),

我知道宏可以扩展为模式,bind_alternatives 的第一个大括号确实有效。是否可以概括为不止一种可能性?如果不是,是什么阻止了它?

最佳答案

宏可以扩展为模式、表达式和项目之类的东西,但不是所有东西;具体来说,宏扩展为完整的 AST 节点,但您在这里处理的不是完整的 AST 节点。

一个match的每个分支表达式可以有一个或多个模式,由竖线分隔,以及一个可选的模式保护(if <em>condition</em>)。这都很特别match -特定语法,因此不是完整的 AST 节点,因此不是宏可以扩展到的东西。

解析器在解析时寻找模式,因此它将宏扩展为模式,在 | 之前结束。 ,这不适合模式语法。宏因此产生了超过可以消耗的量,其余的将因错误而被丢弃。

关于macros - 宏可以扩展为模式组合吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30626147/

相关文章:

rust - 等号在 trait bound 中是什么意思?

vector - 无法通过索引访问向量中的可变引用

clojure - 如何在 ClojureScript 中使用 clojure.tools.macro/name-with-attributes?

xcode - 你如何隐藏基于宏定义的代码?

python - 选择名称遵循 pandas 中给定模式的 DataFrame 列

java - 在 Java 中使用正则表达式提取特定值

c++ - 如何检查函数是否存在

Xcode 预处理器宏

syntax - Some() 在变量赋值的左侧做什么?

docker - 使用 Docker 构建缓存 Rust 依赖项