Pattern match const array of generic length

You can pattern match an array syntactically like that:

let [a, b, c, ...] = array else { panic!() };
let array_3: [_, 3] = [a, b, c];

But how to be able to pattern match depending on the constant?

const COUNT: usize = env!("COUNT");

let [???] = array else { panic!() };
let array_n: [_, COUNT] = ???;

Something like this looks okay, but it will not support multiple arrays with different lengths:

let [a, rest @ ..] = array;
let array_n: [_, COUNT] = from_fn(|i| rest[i]);

I'm not sure that I understand your goal here.
What are you trying to achieve?
I.e. what is your example input and the respective desired output?

Also not sure what you’re going for but one approach could be to observe the len method of &[T] aka slice is const (maybe not necessary)

Can you try this?

match { my_array }.len() {
    3 => …,
    1..=2 => …,
    0 => …,
}

Edit: the curly braces around my_array are purely for explanation, not sure how that impacts the code

Edit2: maybe you could match on the length first and then match on the contents if you need particular patterns of the contents?

It’s possible you’re looking for “destructuring”

1 Like

If I know precise number of elements in each array, I can create them like this:

let [a, b, c, d, e, f, g, ...] = array else { panic!() };
let array_3: [_, 3] = [a, b, c];
let array_4: [_, 4] = [d, e, f, g];

But what if I want to use constants instead of 3 and 4? Is there any "clear" way to create such arrays?

I am also not sure if I understand, but are you looking for something like this:

let Some((array_n, rest)) = array.split_first_chunk::<N>() else { panic!() };
// now it is array_n: &[_; N]
let Some((array_m, _)) = rest.split_first_chunk::<M>() else { panic!() };

... but for owned values?

If you want to use only Copy values, this should work:

let Some((&array_n, rest)) = array.split_first_chunk::<N>() else { panic!() };
// now it is array_n: [_; N]
let Some((&array_m, _)) = rest.split_first_chunk::<M>() else { panic!() };
4 Likes

You can also try_into() a slice into an array of the same length (if Copy), or an array reference:

let arr: [i32; LEN] = array[0..LEN].try_into() else { … }

Unfortunately Rust’s type system cannot currently express the fact that taking an N-length prefix array of an M-length array cannot fail if N<=M.

Edit: actually it’s possible nowadays using const { panic!() }, you still need to unwrap but at least it’s guaranteed to succeed. Once Result::unwrap is const (Option::unwrap already is), then it will be 100% compile-time checked.