我有这样的想法:
macro_rules! mymatch {
($obj:ident, ($matcher:tt => $result:tt),*) => {
match $obj {
$matcher
},
}
}
mymatch! {
x,
10 => "Ten",
n if n < 5 => "Less than 5"
}
Run Code Online (Sandbox Code Playgroud)
我不想重新实现该match声明,但我确实想在两边添加额外的内容。但是,我不知道如何匹配匹配语句的内容。
您的语法有一些问题。如果您想匹配重复的模式,那么您需要以 开始分组$,如下所示:$($matcher:tt => $result:tt),*。
接下来,您可能想要匹配的不仅仅是标识符,因为任何表达式都可以有效匹配,因此将其更改为expr. 在 的左边,=>您将需要一个pat(模式),而不是一个tt。令牌树是通用的,但例如, inn if n < 5将匹配 5 个单独的令牌 - n、if、n、<、5- 并且通常只有在其他方法不起作用时才依赖它。结果也是如此 - 这expr也应该是一个(表达式)。
if < 5暂时忽略守卫,你可以匹配以下内容:
my_match! {
x,
10 => "Ten",
_ => "something else"
}
Run Code Online (Sandbox Code Playgroud)
使用以下宏:
macro_rules! my_match {
($obj:expr, $($matcher:pat => $result:expr),*) => {
match $obj {
$($matcher => $result),*
}
}
}
Run Code Online (Sandbox Code Playgroud)
守卫很烦人,因为它们是可选的,但?量词还不稳定。相反,您必须使用*(0 或更多),即使它在技术上匹配的数量超出了您的需要。
完整的宏是:
macro_rules! my_match {
($obj:expr, $($matcher:pat $(if $pred:expr)* => $result:expr),*) => {
match $obj {
$($matcher $(if $pred)* => $result),*
}
}
}
Run Code Online (Sandbox Code Playgroud)
并支持这种用法:
let x = 7;
let s = my_match! {
x,
10 => "Ten",
n if x < 5 => "Less than 5",
_ => "something else"
};
println!("s = {:?}", s); // "Something else"
Run Code Online (Sandbox Code Playgroud)
块也是一个expr,所以这也是有效的:
my_match! {
x,
10 => "Ten",
n if x < 5 => {
println!("it was {}", n);
"Less than 5"
},
_ => "something else"
};
Run Code Online (Sandbox Code Playgroud)