我想知道有什么方法可以将一个模式作为函数参数来传递。
我有一个方法。
pub enum KEYWORD {
assign(ASSIGN),
symbol(SYMBOL),
illegal
}
pub enum ASSIGN { /* some enums */ }
pub enum SYMBOL { /* some enums */ }
现在,我知道我可以用 match!
或我做的 expect!
宏,以配合我的键 l.key()
所以。
macro_rules! expect(($e:expr, $p:pat) => (
match $e {
$p => { true },
_ => { false }
}
));
expect!(l.key(), KEYWORD::symbol(_));
然而,我需要更多的情况下,我需要通过。KEYWORD::symbol(_)
作为函数参数,例如
impl l {
pub fn expect_as_func(&self, KEYWORD) { /* some code */ }
}
l.expect_as_func(KEYWORD::symbol(_));
但是这个 l.expect_as_func(KEYWORD::symbol(_));
是错误的,因为我使用的不是一个值,而是一个模式。
我试着用 proc_macro
和 TokenStream
:
pub fn expect(&mut self, patt: TokenStream) -> bool {
match &self {
patt => { true },
_ => { false }
}
}
但这也不行。
从人机工程学的角度来看,你可以尝试实现以下函数 is_assign
, is_symbol
, is_illegal
在你的枚举上。
impl KEYWORD {
fn is_assign(&self) -> bool {
match self {
KEYWORD::assign(_) => true,
_ => false,
}
}
// and so on
}
现在,由于这一切都变得乏味, 你可以创建一个宏来生成这些函数。
macro_rules! generate_is(($variant: pat, $fn_name: ident) => {
fn $fn_name(&self) -> bool {
match self {
$variant => true,
_ => false,
}
}
});
impl KEYWORD {
generate_is!(KEYWORD::assign(_), is_assign);
generate_is!(KEYWORD::symbol(_), is_symbol);
generate_is!(KEYWORD::illegal, is_illegal);
}
这样,调用者只需说 keyword.is_assign()
或类似的)。
然后,在此基础上,你可以尝试发明一些能自动生成 is_...
-从你的枚举中获取函数。(可能是通过一个程序化的宏)。
我想说的是,从根本上说,模式不是应该作为函数参数传递到函数中的东西:而是应该传递一个具体的类型实例。
无论如何,如果这个任务的上下文真的需要它,你可以将整个函数实现为一个叫做 TokenSteam
内有图案,通过 proc_macro
. 类似于以下内容:
let tokens = quote! {
pub fn expect(&mut self) -> bool {
match &self {
#patt => { true },
_ => { false }
}
}
};