Macros 如何在Rust中编写宏以匹配集合中的任何元素?

Macros 如何在Rust中编写宏以匹配集合中的任何元素?,macros,rust,variadic-macros,Macros,Rust,Variadic Macros,在C语言中,我习惯于: if (ELEM(value, a, b, c)) { ... } 这是一个具有可变参数数的宏,以避免键入 if (value == a || value == b || value == c) { ... } 在中可以看到一个C示例 这在铁锈中可能吗?我假设它将使用匹配。如果是这样,如何使用可变参数来实现这一点?宏规则!化学机械抛光{ //除锈1.11版及之前版本。 (@as_expr$e:expr)=>{$e}; ($lhs:expr,$cmp:tt any$($

在C语言中,我习惯于:

if (ELEM(value, a, b, c)) { ... }
这是一个具有可变参数数的宏,以避免键入

if (value == a || value == b || value == c) { ... }
在中可以看到一个C示例

这在铁锈中可能吗?我假设它将使用
匹配
。如果是这样,如何使用可变参数来实现这一点?

宏规则!化学机械抛光{
//除锈1.11版及之前版本。
(@as_expr$e:expr)=>{$e};
($lhs:expr,$cmp:tt any$($rhss:expr),*)=>{
//我们这样做是为了将“$lhs”绑定到一个名称,这样就不会对其进行多次计算
//使用前导下划线以避免未使用的变量警告
//在no`rhs`s的退化情况下。
匹配$lhs{u lhs=>{
假| |$(
cmp!(@as_expr\u lhs$cmp$rhss)
) || *
//^-用作术语之间的*分隔符*
}}
};
//相同,但适用于“所有”。
($lhs:expr,$cmp:tt all$($rhss:expr),*)=>{
匹配$lhs{u lhs=>{
正确&&$(cmp!(@as_expr_lhs$cmp$rhss))&&*
}}
};
}
fn main(){
设值=2;
如果cmp!(值,==任何1、2、3){
println!(“真!值:{:?}”,值);
}

如果cmp!(值*2,!=全部5、7、1是,这是可能的,下面的宏将展开以执行每个检查

macro_rules! elem {
    ($n:expr, $( $hs:expr ),*) => ($( $n == $hs )||* );
}

fn main() {
    if elem!(4, 1, 2, 3, 4) {
        println!("OK");
    }
}


多亏了IRC中的@vfs on#rust。

首先,如果您的
a
b
c
是具体的值,您可以使用
match

fn main() {
    let x = 42;

    match x {
        1 | 2 | 3 => println!("foo"),
        42 => println!("bar"),
        _ => println!("nope"),
    }
}
如果要匹配变量,需要编写
match
臂,如下所示:

match x {
    x if x == a || x == b || x == c => println!("foo"),
    42 => println!("bar"),
    _ => println!("nope"),
}
…这基本上就是你想要避免的

但是:C宏的直接翻译也是可能的

macro_rules! elem {
    ($val:expr, $($var:expr),*) => {
        $($val == $var)||*
    }
}

fn main() {
    let y = 42;
    let x = 42;

    if elem!(x, 1, 3, y) {
        println!("{}", x);
    }
}

我倾向于在没有宏的情况下编写这篇文章,利用数组上的
contains

fn main() {
    if [1, 2, 3, 4].contains(&4) {
        println!("OK");
    }
}

很难预测优化后会发生什么情况,但如果绝对性能是一个目标,那么最好对每种方法进行基准测试。

Rust v1.11及之前版本-这是否意味着丑陋的疣最终得到了修复?@Shepmaster显然。我自己还没有机会对其进行彻底测试,但看起来重新分析的技巧可能会有帮助e即将退出。虽然不如对实际代码进行基准测试,但这里有一篇文章(2007年)介绍了LLVM如何优化/降低开关语句: