rust - Modulo operator in a match expression - Stack Overflow

admin2025-04-26  3

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

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

Share Improve this question edited Jan 15 at 6:14 Harry asked Jan 15 at 6:06 HarryHarry 3,3721 gold badge24 silver badges47 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 6

There's really only two primary solutions here:

  1. Use _ for one of the arms so that you don't need a third:

    match num % 2 {
        0 => Either::Left(num),
        _ => Either::Right(num),
    }
    
  2. 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.

转载请注明原文地址:http://www.anycun.com/QandA/1745597320a90969.html