非穷举模式 - Rust 匹配表达式

fre*_*esh 4 pattern-matching rust

我有以下 Rust 代码的问题:

pub fn median(v: &Vec<i32>) -> f32 {
    let len = v.len();
    match len % 2 {
        0 => (v[len / 2 - 1] + v[len / 2]) as f32 / 2 as f32,
        1 => v[(len - 1) / 2] as f32,
    }
}
Run Code Online (Sandbox Code Playgroud)

由于“非详尽模式”错误,此代码无法编译。这是为什么?% 运算符返回什么?

Alo*_*oso 7

最简单的修复方法是使用_而不是1

match len % 2 {
    0 => (v[len / 2 - 1] + v[len / 2]) as f32 / 2 as f32,
    _ => v[(len - 1) / 2] as f32,
}
Run Code Online (Sandbox Code Playgroud)

因为len在第二个分支中 是奇数且非负,(len - 1) / 2因此与 相同len / 2。我会像这样简化它:

let mid = v.len() / 2;
match v.len() % 2 {
    0 => (v[mid - 1] + v[mid]) as f32 / 2.0,
    _ => v[mid] as f32,
}
Run Code Online (Sandbox Code Playgroud)


use*_*968 6

编译器不够聪明,无法确定 的结果len % 2只能是01。对于结果为其他值的情况,它需要匹配臂。您可以通过明确说明这些情况是不可能的来解决这个问题:

match len % 2 {
    0 => (v[len / 2 - 1] + v[len / 2]) as f32 / 2 as f32,
    1 => v[(len - 1) / 2] as f32,
    _ => unreachable!()
}
Run Code Online (Sandbox Code Playgroud)

_将匹配前面没有提到任何其他值。该unreachable!()告诉编译器“这个代码将不会执行”,但会导致panic!()以防万一它实际上执行。这样,该程序始终是正确的,几乎没有成本。

编译器的未来版本可能会发现这些值2..或不可能。

%remainder operator(不与被共熔mod-运算符)。

  • 作为一个快速旁注:在发布模式下,编译器可以检测到只有“0”和“1”是可能的,因此完全消除“_”分支。https://rust.godbolt.org/z/PVgltd (2认同)