将模式作为函数参数传递?
Pass a pattern as a function parameter?
我想知道有没有办法将模式作为函数参数传递。
我有:
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 }
}
}
但这也不起作用。
我想说的是,从根本上说,模式不是应该作为函数参数传递给函数的东西:而是应该传递类型的具体实例。
无论如何,如果此任务的上下文确实需要它,您可以将整个函数实现为 TokenSteam
,并通过 proc_macro
在内部使用模式。类似于以下内容:
let tokens = quote! {
pub fn expect(&mut self) -> 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_...
函数。 (可能通过程序宏。)
我想知道有没有办法将模式作为函数参数传递。
我有:
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 }
}
}
但这也不起作用。
我想说的是,从根本上说,模式不是应该作为函数参数传递给函数的东西:而是应该传递类型的具体实例。
无论如何,如果此任务的上下文确实需要它,您可以将整个函数实现为 TokenSteam
,并通过 proc_macro
在内部使用模式。类似于以下内容:
let tokens = quote! {
pub fn expect(&mut self) -> 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_...
函数。 (可能通过程序宏。)