基本上,我有一个看起来像这样的宏:
macro_rules! my_macro {
( $expr:expr; $( $pat:pat ),* ) => {
match $expr {
$(
$pat => $(some-macro-magic-here),
)*
}
}
}
是否有可以放入$(some-macro-magic-here)
的内容,所以
my_macro!(foo; A, B, C)
将扩展为
match foo {
A => 2,
B => 4,
C => 6,
}
?
还有其他方法可以使我有效地让我“枚举”宏的输入顺序吗?
我想我可能可以写一个递归宏来获得类似的效果,但是我想知道是否有比我所想的更优雅/惯用的方式
答案 0 :(得分:1)
因为不允许宏以任何形式存储或操作“变量”,所以这个问题变得非常困难。但是,您可以使用迭代器来实现相同的效果,方法是创建一个迭代器,以所需的方式“枚举”输入(例如,使用std::iter::successors
),然后简单地调用{{1 }}在iterator.next().unwrap()
中。
答案 1 :(得分:1)
您无法创建这样的match
语句,因为Rust不允许通过宏创建match
分支,因此这暂时不起作用:
match val {
my_macro! (A, B, C)
}
但是,在这种情况下,我们可以使用嵌套的if let
块并使用递归宏来“破解”:
macro_rules! my_macro {
($expr:expr; $($pat:pat),*) => {
my_macro!($expr; 2, 2; $($pat),*)
};
($expr:expr; $curr:expr, $step:literal; $pat:pat) => {
if let $pat = $expr {
$curr
} else {
unreachable!()
}
};
($expr:expr; $curr:expr, $step:literal; $pat:pat, $($rest:pat),*) => {
if let $pat = $expr {
$curr
} else {
my_macro! ($expr; $curr+$step, $step; $($rest),*)
}
}
}
它将生成嵌套条目,并添加足够的2
以创建预期的常量。或者,您可以将其替换为乘法,但是无论如何应该由编译器对其进行优化。