How to match on different length slices?

The way I match different length slices right now is just plain terrible. This way it is really hard to match on [usize; 99] for example. What is the best way to do this if I want to keep the match and the function signatures?

fn do_thing(numbers: &[usize]) {
    match numbers {
        [a, b, c] => handle_three([*a, *b, *c]), // signiture is handle_three(_: [usize; 3])
        [a, b, c, d] => handle_four([*a, *b, *c, *d]), // signiture is handle_four(_: [usize; 4])
        _ => panic!("Must be exactly 3 or 4 numbers!"),
    }
}

Playground example

One option is this:

fn do_thing(numbers: &[usize]) {
    match numbers.len() {
        3 => handle_three(numbers.try_into().unwrap()),
        4 => handle_four(numbers.try_into().unwrap()),
        _ => panic!("Must be exactly 3 or 4 numbers!"),
    }
}
2 Likes

That is much better! Thanks :slight_smile:

For my particular problem I had to use:

TryInto::<[usize; 3]>::try_into(numbers).unwrap()

But only because I use it with different functions and an extra into:

fn do_thing(numbers: &[usize]) {
    match numbers.len() {
        3 => handle_three(TryInto::<[usize; 3]>::try_into(numbers).unwrap().into()),
        4 => handle_four(TryInto::<[usize; 4]>::try_into(numbers).unwrap().into()),
        _ => panic!("Must be exactly 3 or 4 numbers!"),
    }
}
fn do_thing(numbers: &[usize]) {
    use std::convert::TryInto;

    if let Ok(arr) = numbers.try_into() {
        handle_three(arr)
    else if let Ok(arr) = numbers.try_into() {
        handle_four(arr)
    else {
        panic!("Must be exactly 3 or 4 numbers!")
    }
}
3 Likes