「初看声明宏」匹配

「这是我参与11月更文挑战的第 9 天,活动详情查看:2021最后一次更文挑战


匹配

这个越到后面你会越清晰,现在直接告诉你:其实类似于 regex。你可以定义特定的参数,固定的值,定义可接受的重复值等等。总之如果你对正则很熟悉,这一块应该没有问题。

下面来看看关于匹配中几个比较重要的事情。

变量

变量以 $ 开头(例如,$value:expr)。它们的结构是:$ name : designator。

  • $: 都是固定的。
  • 名称遵循Rust变量的惯例。当在transcriber中使用时(见下文),被称为元变量。
  • 标志符不是变量类型。你可以把它们看作是 "语法类别"。在这里,我会坚持使用表达式(expr),因为Rust是 "主要是一种表达式语言"。在这里可以找到一些可能的标志符。

注意:对于 "designator" 这个名字,似乎还没有达成共识。小册 中称它为 "捕获";Rustbook 中称它为 "片段指定器";你也会发现有人把它们称为 "类型"。在从源码跳转到源码时要注意这一点。在这里,我将坚持使用标志符这个称呼,正如Rust中提出的例子。

固定参数

这里没有什么神秘的。只需添加它们,不需要$,例如:

macro_rules! power {
    ($value:expr, squared) => { $value.pow(2) }
}

fn main() {
    println!("{}", power!(3_i32, squared));
}
复制代码

这里有一些事情还没有解释。我现在要谈一谈它们。

分隔符

一些标志符需要一些具体的后续工作。表达式需要其中之一:=>/,/;。这就是为什么我不得不在$value:expr和固定值的平方之间添加一个逗号。你可以在 here 找到一个完整的列表。

多匹配

如果我们想让我们的宏不仅计算一个数字的平方,还能计算一个数字的立方,这个该怎么做?

macro_rules! power {
    ($value:expr, squared) => { $value.pow(2_i32) }
    ($value:expr, cubed) => { $value.pow(3_i32) }
}
复制代码

多重匹配可以用来匹配不同逻辑。通常情况下,你要从最具体的到最不具体的,来写匹配规则,这样你的调用就不会落入错误的匹配。更多的解释可以在这里找到。

重复项

我们使用的大多数宏都允许有灵活的输入数量。

例如,我们可以调用 vec![2]vec![1,2,3]。这就是匹配与Regex最相似的地方。基本上,我们把变量包在$()里面,然后用一个重复操作符推进后面的匹配。

  • * → 表示任何数量的重复
  • + → 表示任何数量,但至少有一个
  • ? → 表示一个可选项,有零个或一个出现

比方说,我们想加N个数字。我们需要至少两个加数。所以我们将有:第一个值;和一个或多个(+)第二个值:

macro_rules! adder {
    ($left:expr, $($right:expr),+) => {}
}

fn main() {
    adder!(1, 2, 3, 4);
}
复制代码

猜你喜欢

转载自juejin.im/post/7031185935551184932