I need to partition a given vec of numbers into odds and evens. To do that I'm using itertools
crate to perform the partition like below. Since modulo(%)
operator by 2
can possibly return -1, 0, 1
, rust compiler still throws an error to include patterns of i32::MIN..=-2_i32
and 2_i32..=i32::MAX
, which is kind of not good looking. I can overcoome this issue by including the _
pattern, but would like to know a better way to handle this kind of scenario.
use itertools::{Either, Itertools}; // 0.14.0;
fn print(nums: &Vec<i32>) {
for num in nums {
print!("{}, ", num);
}
println!();
}
fn main() {
let nums = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
print(&nums);
let (evens, odds): (Vec<_>, Vec<_>) = nums.iter()
.partition_map(|num| match num % 2 {
0 => Either::Left(num),
1 | -1 => Either::Right(num),
_ => todo!(),
});
print(&nums);
print(&evens);
print(&odds);
}
This could be a problem in case of code coverage related stuff, since _
pattern never going to be executed no matter what's the input
There's really only two primary solutions here:
Use _
for one of the arms so that you don't need a third:
match num % 2 {
0 => Either::Left(num),
_ => Either::Right(num),
}
As you've said, add an extra _
arm. In these situations, you can use unreachable!()
-- indeed, this is one of the documented uses for it.
match num % 2 {
0 => Either::Left(num),
-1 | 1 => Either::Right(num),
_ => unreachable!(),
}
I would consider either of these options idiomatic. Note that while the compiler doesn't know that the _
arm cannot be reached, the optimizer does and will elide that arm.