PartialEq / Eq正常工作时为什么匹配不起作用?

时间:2017-07-03 15:48:55

标签: rust

我有这个简单的代码:

#[derive(Copy, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash)]
struct NodeIndex(u32);

fn main() {
    let i = NodeIndex(5323);
    let from = NodeIndex(21030);
    let to = NodeIndex(21031);

    println!("from == i => {}, to == i => {}", from == i, to == i);

    match i {
        from => println!("1"),
        to => println!("2"),
        _ => println!("other"),
    }
}

打印:

from == i => false, to == i => false
1

所以i != fromi != tomatch致电from => println!("1"),, 发生了什么事?

1 个答案:

答案 0 :(得分:6)

通过查看编译器的警告可能更容易理解发生了什么:

warning: unused variable: `from`
  --> src/main.rs:12:9
   |
12 |         from => println!("1"),
   |         ^^^^
   |
   = note: #[warn(unused_variables)] on by default

warning: unreachable pattern
  --> src/main.rs:13:9
   |
13 |         to => println!("2"),
   |         ^^ this is an unreachable pattern
   |
   = note: #[warn(unreachable_patterns)] on by default
note: this pattern matches any value
  --> src/main.rs:12:9
   |
12 |         from => println!("1"),
   |         ^^^^

warning: unused variable: `to`
  --> src/main.rs:13:9
   |
13 |         to => println!("2"),
   |         ^^
   |
   = note: #[warn(unused_variables)] on by default

warning: unreachable pattern
  --> src/main.rs:14:9
   |
14 |         _ => println!("other"),
   |         ^ this is an unreachable pattern
   |
   = note: #[warn(unreachable_patterns)] on by default
note: this pattern matches any value
  --> src/main.rs:12:9
   |
12 |         from => println!("1"),
   |         ^^^^

基本上,标识符fromto 不会引用绑定中包含的值。它们是新的绑定,碰巧匹配任何东西。新的标识符名称也会发生同样的事情:

match i {
    x => println!("1"),
    y => println!("2"),
    _ => println!("other"),
}

由于程序始终与第一种情况相匹配,因此始终打印“1”。

您可以将fromto声明为const来获得预期结果:

const from: NodeIndex = NodeIndex(21030);
const to: NodeIndex = NodeIndex(21031);

或直接使用对象文字:

match i {
    NodeIndex(21030) => println!("1"),
    NodeIndex(21031) => println!("2"),
    _ => println!("other"),
}

如果fromto的值仅在运行时已知,则可以使用if / else语句:

if n == from {
    println!("1");
} else if n == to {
    println!("2");
} else {
    println!("other");
}

...或在匹配期间添加if子句(在运行时评估):

match i {
    n if n == from => println!("1"),
    n if n == to => println!("2"),
    _ => println!("other"),
}