Str*_*des 0 macros pattern-matching rust
我试图压缩一些具有类似结构的重复代码:
match self.foo() {
None => self.bar(),
Some(MyStruct { foo: x, .. }) => match x {
Pattern1 => result,
Pattern2 => {
block_result
}
}
}
Run Code Online (Sandbox Code Playgroud)
我想写的类似于:
my_macro!(
Pattern1 => result,
Pattern2 => {
block_result
}
)
Run Code Online (Sandbox Code Playgroud)
避免重复None处理和MyStruct解构.
这看起来应该很简单,因为它基本上只是将宏体代入匹配表达式,但我实际上看不到任何方法可以做到这一点.
我尝试按如下方式编写宏:
macro_rules! my_macro (
($($pat:pat => $result:expr,)*) => (
match self.foo() {
None => self.bar(),
Some(MyStruct { foo: x, .. }) => match x {
$(
$pat => $result,
)*
},
}
);
)
Run Code Online (Sandbox Code Playgroud)
但这失败了,因为匹配臂的RHS可以是表达式或块(并且它也没有处理可选地省略最后一个臂的逗号).据我所知,没有办法指定宏模式的一部分可以是块或表达式,所以我想不出解决这个问题的方法.
理想情况下,我想这样做而不必编写复杂的模式来解构匹配的主体只是为了再次将它们重新组合在一起,但我认为没有任何指示符可以接受匹配表达式的主体.
你会怎么写这个宏?如果没有编写编译器插件,它甚至可以吗?
我不确定你为什么这么做
这失败了,因为匹配臂的RHS可以是表达式或块
在Rust匹配中,arm总是表达式,而恰好是块也是表达式.
你的宏有两个问题.首先,正如您所注意到的,您的宏不会处理省略最后一个逗号.这可以很容易地解决:您只需更改此模式:
$($pat:pat => $result:expr,)*
Run Code Online (Sandbox Code Playgroud)
进入这一个:
$($pat:pat => $result:expr),*
Run Code Online (Sandbox Code Playgroud)
并且它的用法也应该改变:
$(
$pat => $result,
)*
Run Code Online (Sandbox Code Playgroud)
至
$(
$pat => $result
),*
Run Code Online (Sandbox Code Playgroud)
第二个问题是,除非你在包含self标识符的范围内定义这个宏(即在方法内部),否则它将无法正常工作,因为卫生 - self你使用的标识符self.foo()和self.bar()宏体中的调用将不同于宏观扩张现场的那个.作为一般规则,您始终需要将要在宏扩展站点上使用的标识符作为宏的参数传递,除非在已存在这些标识符的范围中定义此宏.
所以,宏的最终变体是这样的:
macro_rules! my_macro (
($_self:expr, $($pat:pat => $result:expr),*) => (
match $_self.foo() {
None => $_self.bar(),
Some(MyStruct { foo: x, .. }) => match x {
$(
$pat => $result
),*
},
}
);
)
Run Code Online (Sandbox Code Playgroud)
它确实可以正常工作.
您可以在官方指南中找到有关宏以及如何编写宏的更多信息.
| 归档时间: |
|
| 查看次数: |
1495 次 |
| 最近记录: |