在宏中匹配下划线而不是标识



我正在创建一个匹配两个表达式和一个标识符的宏。如果不需要标识符,我希望能够忽略标识符,但是如果我在那里使用_编译器似乎会抱怨。

我的宏:

macro_rules! if_some {
($x:expr, $id:ident, $expr:expr) => {
match $x {
None => None,
Some($id) => Some($expr),
}
};
}

我想做什么:

if_some!(obtain_an_option(), x, do_something_with(x))

if_some!(obtain_an_option(), _, do_something())

第二次调用失败。

我通过定义第二个不接收标识符的宏if_some_!来解决这个问题(我也不能使用第二个模式(。我敢肯定有一种方法可以说"这里接受标识符或只是_.

也许已经有一个宏/功能了(就像现在我想Option::map一样(......不过,现在就好了。

最简单的方法是添加与下划线匹配的第二个臂:

macro_rules! if_some {
($x:expr, _, $expr:expr) => {
match $x {
None => None,
Some(_) => Some($expr),
}
};
($x:expr, $id:ident, $expr:expr) => {
match $x {
None => None,
Some($id) => Some($expr),
}
};
}

而且,是的,这听起来像你只是想要Option::map.

Option::map

似乎是这个特定问题的最佳解决方案,但是当你真的需要一个同时期望标识和_作为模式的宏时,你也可以使用$p:pat片段。片段当然接受更广泛的模式,如(ref x, y),但通常这是可以接受的。

macro_rules! if_some {
($x:expr, $p:pat, $expr:expr) => {
match $x {
None => None,
Some($p) => Some($expr),
}
};
}
fn main() {
println!("{:?}", if_some!(Some(12), x, x + 1)); // Some(13)
println!("{:?}", if_some!(Some(12), _, 1)); // Some(1)
}

最新更新