我需要一个宏,以防止需要写下面的代码超过2的十二次幂:
pub(crate) fn calc(samples: &[f32]) -> Vec<Complex32> {
let buffer = samples;
let mut res = {
if buffer.len() == 2 {
let mut buffer: [_; 2] = buffer.try_into().unwrap();
real::rfft_2(&mut buffer).to_vec()
} else if buffer.len() == 4 {
let mut buffer: [_; 4] = buffer.try_into().unwrap();
real::rfft_4(&mut buffer).to_vec()
/// ..
} else if buffer.len() == 16384 {
let mut buffer: [_; 16384] = buffer.try_into().unwrap();
real::rfft_16384(&mut buffer).to_vec()
} else {
panic!(
"`microfft::real` only supports powers of 2 between 2 and 16384 for the amount of samples!"
);
}
然而,我不知道如何在Rust宏定义中表达这一点。宏将被如下调用:generate_ifs!(buffer, 2, 4, 8, 16, 32, 64, 128, 256, ..., 16384)
可能,我需要这样的:
macro_rules! generate_ifs {
($buffer:ident, $e:literal) => {
{
}
};
($buffer:ident, $e:literal, $($es:literal),+) => {{
generate_ifs! { $buffer:ident, $e }
// do something special to generate "else if"
generate_ifs! { $buffer:ident, $($es),+ }
}};
}
但我看不出最后会有什么结果。
2条答案
按热度按时间svmlkihl1#
如果你已经枚举了2的所有幂次,你也可以写出函数的标识符(
rfft_2
)来得到一个简短的解决方案:我使用了一个技巧,通过在开始时添加一个
if false
分支来解决if
与else if
的问题。如果您想在宏调用中省略函数名,这会变得更加困难(如果使用
macro_rules!
不是不可能的话),例如,请参见以下问题:Interpolateident
in string literal inmacro_rules!
au9on6nz2#
你可以在这里使用闭包,在你的宏调用中创建闭包,然后立即调用它,返回它的结果,这允许你在每个
if
-语句中依赖return
,所以你不需要else
块:您可以找到完整的示例here.