【问题标题】:Why does the order of parameters matter when using the matches! macro?为什么使用匹配时参数的顺序很重要!宏?
【发布时间】:2021-10-28 11:00:12
【问题描述】:

我正在尝试将存储在结构向量中的枚举类型变量与作为参数传递给我的函数的相同类型的变量进行比较。因此,两个枚举都存储在变量中。但是,我得到了意想不到的结果。我正在使用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

【问题讨论】:

    标签: rust enums comparison


    【解决方案1】:

    matches! 宏不对称:第一个操作数是要测试的表达式,第二个操作数是 pattern 以尝试匹配第一个操作数。如果不遵循此顺序,结果可能会出乎意料。

    虽然前两个 matches! 格式良好并且可以满足您的期望,但第三个和第四个很可能不是您想要的。

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

    要测试的表达式是字面值Foo::B,模式是一个新的标识符,第三个例子是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
    

    另见:

    【讨论】:

    • 谢谢!您提供的链接应该回答我的后续问题,即如何比较 match 语句中变量中保存的枚举。我认为 (n if n == a) 模式应该可以工作。
    【解决方案2】:

    感谢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
    

    【讨论】:

    • 请注意,在此示例中使用 match 表达式并没有太多好处。使用一系列 if-else 表达式(例如 let s = if a == b { "a matches b" } else if a == a { "a matches a" } else { "no match" };)也可以实现相同的目的。 if 匹配大括号中的保护在与更复杂的模式结合使用时很有用。
    猜你喜欢
    • 2020-11-22
    • 1970-01-01
    • 1970-01-01
    • 2014-09-13
    • 2015-03-10
    • 2022-01-06
    • 2013-05-18
    • 1970-01-01
    相关资源
    最近更新 更多