按位还是匹配?

时间:2018-09-04 18:28:13

标签: rust bitwise-operators

我有一个变量,该变量由几个标志进行或运算而成,并且我想测试我的值是它们的哪个组合,并对其执行操作。不幸的是,|运算符在match语句中具有不同的含义,因此我无法编写

match x {
    (FLAG1 | FLAG2) => return 5;
    (FLAG1 | FLAG3) => return 6;
    (FLAG2 | FLAG3) => return y;
    _ => return 0;
}

,相反,我需要预先计算(FLAG1 | FLAG2),依此类推,使我的代码丑陋且不可读。有更好的方法吗?

3 个答案:

答案 0 :(得分:4)

您可以通过使用一系列可能的选项来解决此限制:

const FLAG1: usize = 1;
const FLAG2: usize = 2;
const FLAG3: usize = 3;

fn main() {
    let x = 1;
    let y = 10;

    let options = [
        (FLAG1 | FLAG2, 5), 
        (FLAG1 | FLAG3, 6), 
        (FLAG2 | FLAG3, y)
    ];

    let result = options.iter()
                        .find(|(calc, _)| *calc == x)
                        .map(|(_, ret)| *ret)
                        .unwrap_or(0);
}

根据要涵盖的变体数量,这可能是一个可行的解决方案。

答案 1 :(得分:3)

match表达式的每个分支的左侧是 pattern 而不是 expression 。这意味着您只能在那里进行模式匹配。您不能使用运算符,访问器和函数调用。

不幸的是,我认为您可能会坚持使用if..else

if x == FLAG1 | FLAG2 { return 5 }
else if x == FLAG1 | FLAG2 { return 6 }
else if x == FLAG1 | FLAG2 { return y }
else { return 0 };

但是,由于if..else(和match)是表达式,因此您至少可以消除重复的return

return if x == FLAG1 | FLAG2 { 5 }
else if x == FLAG1 | FLAG2 { 6 }
else if x == FLAG1 | FLAG2 { y }
else { 0 };

答案 2 :(得分:1)

我写了一个小宏,用match卫士将您的代码转换成if。我将其命名为switch!,因为它的工作方式与其他语言中的switch类似。

https://github.com/camsteffen/switch-statement-rust

switch! { x;
    FLAG1 | FLAG2 => return 5,
    FLAG1 | FLAG3 => return 6,
    FLAG2 | FLAG3 => return y,
    _ => return 0,
}