为什么在使用匹配时参数的顺序很重要!宏观?

Why does the order of parameters matter when using the matches! macro?

我正在尝试比较存储在结构向量中的枚举类型的变量与作为参数传递到我的函数中的相同类型的变量。因此,两个枚举都存储在变量中。但是,我得到了意想不到的结果。我正在使用 matches!() 宏进行比较。谁能解释这种行为?

enum Foo {
    A,
    B,
}


fn main() {
    let a = Foo::A;
    if matches!(a, Foo::A) { println!("expected") }
    if matches!(a, Foo::B) { println!("not expected 1") }
    if matches!(Foo::B, a) { println!("not expected 2") }

    let b =  Foo::B;
    if matches!(a, b) { println!("not expected 3") }
}

输出:

expected
not expected 2
not expected 3

matches! macro is not symmetrical: the first operand is the expression to be tested and the second operand is a pattern 尝试匹配第一个操作数。如果不遵循这个顺序,结果可能会出乎意料。

虽然前两个 matches! 格式正确并且符合您的预期,但第三个和第四个很可能不是您想要的。

matches!(Foo::B, a) // test `Foo::B` against pattern `a`
matches!(a, b) // test `a` against pattern `b`

要测试的表达式是字面值Foo::B,pattern是一个新的标识符,第三个例子是a,第四个例子是b。由于模式只是一个标识符,它会匹配任何表达式。它与预先声明的变量 ab 完全无关。即使 b 不存在,下面的代码仍然可以编译。

let a = Foo::A;
matches!(a, b);

另请注意,这些 if 语句将打印警告,因为根据模式创建了一个新变量,但未使用。

warning: unused variable: `a`
 --> src/main.rs:7:25
  |
7 |     if matches!(Foo::B, a) { println!("not expected 2") }
  |                         ^ help: if this is intentional, prefix it with an underscore: `_a`
  |
  = note: `#[warn(unused_variables)]` on by default

另请参阅:

感谢 E_net4 the curator 的有用回答。我现在可以使用以下方法获得我期望的行为:

#[derive(PartialEq)]
enum Foo {
    A,
    B,
}


fn main() {
    let a = Foo::A;
    let b = Foo::B;

    let s = match a {
        n if n == b => "a matches b",
        n if n == a => "a matches a",
        _ => "no match"
    };
    println!("{}", s);
}

输出:

a matches a