Ste*_*ein 6 macros pattern-matching rust
我目前正在研究Rust宏,我找不到任何有关重复的详细文档.我想用可选参数创建宏.这是我的想法:
macro_rules! single_opt {
($mand_1, $mand_2, $($opt:expr)* ) =>{
match $opt {
Some(x) => println!("1. {} 2. {}, 3. {}", $mand_1, $mand_2, x);
None => single_opt!($mand_1, $mand_2, "Default");
}
}
}
fn main() {
single_opt!(4,4);
}
Run Code Online (Sandbox Code Playgroud)
这个例子似乎已经过时了,因为我无法编译它.Rust书中非常简短地提到了这个主题.我如何让这个例子起作用?
Fra*_*gné 13
Rust书中有一个相当长的关于宏的章节,但关于重复的部分对例子有点害羞......
有几种方法可以处理宏中的可选参数.如果你有一个只能出现一次的可选参数,那么就不应该使用重复:你应该在宏中定义多个模式,如下所示:
macro_rules! single_opt {
($mand_1:expr, $mand_2:expr) => {
single_opt!($mand_1, $mand_2, "Default")
};
($mand_1:expr, $mand_2:expr, $opt:expr) => {
println!("1. {} 2. {}, 3. {}", $mand_1, $mand_2, $opt)
};
}
fn main() {
single_opt!(4, 4);
}
Run Code Online (Sandbox Code Playgroud)
如果你想允许任意数量的参数,那么你需要重复.您的原始宏不起作用,因为您将逗号放在重复之外,因此您必须调用宏single_opt!(4,4,);.
如果您有一个固定数量的参数后跟一个重复,您可以将逗号放在重复内作为第一个标记:
macro_rules! single_opt {
($mand_1:expr, $mand_2:expr $(, $opt:expr)*) => {
println!("1. {} 2. {}, 3. {}", $mand_1, $mand_2, $($opt),*)
};
}
Run Code Online (Sandbox Code Playgroud)
但是,它在这种特定情况下不起作用:
<anon>:2:33: 2:47 error: `$mand_2:expr` is followed by a sequence repetition, which is not allowed for `expr` fragments
<anon>:2 ($mand_1:expr, $mand_2:expr $(, $opt:expr)*) => {
^~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
所以我们必须回到定义两种模式:
macro_rules! single_opt {
($mand_1:expr, $mand_2:expr) => {
single_opt!($mand_1, $mand_2, "Default")
};
($mand_1:expr, $mand_2:expr, $($opt:expr),*) => {
{
println!("1. {} 2. {}", $mand_1, $mand_2);
$(
println!("opt. {}", $opt);
)*
}
};
}
fn main() {
single_opt!(4, 4, 1, 2);
}
Run Code Online (Sandbox Code Playgroud)
重复采用的形式$( PATTERN ) SEPARATOR COUNT,PATTERN您要重复的模式,SEPARATOR是一个可选的标记,用于分隔每个重复(此处,它是,),并且COUNT是*"零次或多次出现"或+"一次或多次出现".
然后,在宏扩展中,我们需要一个能够访问的重复块$opt.语法完全相同,但请注意,分隔符不必相同(此处,扩展中没有分隔符).