如何避免模数匹配中的“_”大小写

fad*_*bee 11 rust

这味道很难闻:

let millis = time % 1000;
match millis {
    0..=199 => do_something(),
    200..=599 => do_something_else(),
    600..=999 => do_something_altogether_different(),
    _ => panic!("There are only 1,000 ms in a second."),
}
Run Code Online (Sandbox Code Playgroud)

“_”的情况永远不会被调用,就像millis一样time % 1000。

我怎样才能重写这个以便我只有三个分支?

理想情况下,我还想删除重复的 199/200、599/600 和 999/1000/0。

如果最好的解决方案不是,match我很乐意使用其他一些控制结构。

Net*_*ave 16

Rust 使用类型进行匹配,因此它不知道您的逻辑的边界。但你做了。

\n

为了明确你可以使用unreachable!:

\n
\n

表示无法访问的代码。

\n

当编译器无法确定某些代码无法访问时,这非常有用。例如:

\n

将武器与守卫条件相匹配。动态终止的循环。\n动态终止的迭代器。如果代码不可访问的判断被证明是错误的,则程序会立即终止并出现紧急情况!。

\n
\n
let millis = time % 1000;\nmatch millis {\n    0..=199 => do_something(),\n    200..=599 => do_something_else(),\n    600..=999 => do_something_altogether_different(),\n    _ => unreachable!("There are only 1,000 ms in a second."),\n}\n
Run Code Online (Sandbox Code Playgroud)\n

否则,您可以认为最后一个分支是默认分支:

\n
let millis = time % 1000;\nmatch millis {\n    0..=199 => do_something(),\n    200..=599 => do_something_else(),\n    _ => do_something_altogether_different(),\n}\n
Run Code Online (Sandbox Code Playgroud)\n

  • 有趣的是,rustc/LLVM 足够聪明,可以推理“%”和范围,并将两个公式编译为完全相同的(无恐慌)[程序集](https://godbolt.org/z/zar7Eqnj1)。 (4认同)
  • 请注意,为了简洁起见,您可以只输入“unreachable!()” - 由于无法访问代码,因此消息是多余的。但在这种情况下,当模数非常接近匹配时,我可能会选择第二个选项。有时简单的“显而易见”的解决方案是最好的,也是最难想出的 - 感谢您将其包含在答案中。 (2认同)

小智 9

我会使用简单的,if因为每种情况都有一个条件,而且只有少量情况:

if millis < 200 {
    do_something()
} else if millis < 600 {
    do_something_else()
} else {
    do_something_altogether_different()
}
Run Code Online (Sandbox Code Playgroud)

如果你想使用match你也可以if在其中使用 -guards :

match millis {
    x if x < 200 => do_something(),
    x if x < 600 => do_something_else(),
    _ => do_something_altogether_different(),
}
Run Code Online (Sandbox Code Playgroud)

两者都删除了重复的199/ 200...


fad*_*bee 0

这只是 Kevin Reid 答案的改进,它通过颠倒顺序来消除重复:

let millis: u64 = time % 1000;
match millis {
    600.. => todo!(),
    200.. => todo!(),
    0.. => todo!(),
}
Run Code Online (Sandbox Code Playgroud)

我们也可以再省略一个数字,但我不确定这是否是一种改进。

let millis: u64 = time % 1000;
match millis {
    600.. => todo!(),
    200.. => todo!(),
    _ => todo!(),
}
Run Code Online (Sandbox Code Playgroud)