fresh
fresh

Reputation: 411

Non-exhaustive patterns - Rust match expressions

I have an issue with the following Rust code:

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,
    }
}

This code doesn't compile due to a 'Non exhaustive patterns' error. Why is that? What does the % operator return?

Upvotes: 12

Views: 7369

Answers (2)

Aloso
Aloso

Reputation: 5397

The simplest fix is to use _ instead of 1:

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

Because len is odd and non-negative in the second branch, (len - 1) / 2 is the same as len / 2. I would simplify it like this:

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

Upvotes: 8

user2722968
user2722968

Reputation: 16475

The compiler is not smart enough to figure out that the result of len % 2 can only ever be 0 or 1. It demands a match arm for cases where the result is some other value. You can solve this by explicitly saying that those cases are impossible:

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

The _ will match any other value not previously mentioned. The unreachable!() tells the compiler "this code will never execute", but cause a panic!() just in case it does in fact execute. That way, the program is correct all the time at practically no cost.

Future versions of the compiler might figure out that the values 2.. or not possible.

The % is the remainder operator (not to be cofused with the mod-operator).

Upvotes: 15

Related Questions