宏中非常重要的语法: 重复(repetition)
同系列传送门:
重复 (Repetition)
是宏中无比重要的核心级语法, 想发挥宏的强大就必须用到它
该语法, 可以重复一段模式(一些Token), 出现在以下两个地方:
(废话, Rust的声明宏不就这两个主要部分嘛)
假设你要设计一个宏, 进行求和(参数个数不确定):
// Examples:
assert_eq!( 0, sum!() );
assert_eq!( 15, sum!(1,2,3,4,5) );
让我们来看看, 如何使用重复吧
关键在于参数的个数不确定, 因此我们应使用重复语法:
macro_rules! sum {
($($a:expr),*) => {
0 $(+ $a)*
}
}
fn main() {
sum!(); // 0
sum!(5); // 5
sum!(1,2,3,4,5); // 15
}
伪代码表示:
$( Pattern ) Sep RepOp
$( 模式 ) 分隔符 重复符号
它可以被分为三个部分:
模式(Pattern): 被包裹于 $( )
, 用于匹配捕获(在Matcher), 或重复展开(在Transcriber)
分隔符(Separator): 用来分割重复的模式, 比如 vec![1,2,3]
中的逗号
重复符号(Repetition Operator): 对模式匹配次数, 进行说明限制, 不符合就编译报错
以 sum!
为例子, 它在第二个rule中用到了重复:
In Matcher: 模式: $a:expr
是重复的模式, 表示重复地匹配与捕获expr
分割: 每个模式之间用逗号分割, 表示传参时要传入逗号进行匹配
次数: *号, 说明了重复模式的个数, 它被限制为>=0
In Transcriber: 模式: + $a
是重复模式, 比如传入 1,2,3,4,5
时, 会被展开为 0+1+2+3+4+5
分割: 没添加分割符号, 表示展开时, 每个模式之间不会添加sep 次数: 同 Matcher
$()
与 RepOp
是必填的, Sep
是可选的
RepOp 有三种可选项, 有点像正则:
*
表示 模式匹配的次数 >= 0+
表示 模式匹配的次数 >= 1 记忆法-> 联想为正数, 那就>=1 ?
表示 模式匹配的次数 = 0 or 1有一些注意点:
上一篇: p3~> 声明与使用
下一篇: p5~> 卫生性