I'm trying to write a function that pattern matches on a slice with a non-Copy type, like this:
fn f<T>(x: Vec<T>) -> T {
match x.as_slice() {
&[ ... ] // Lots of complicated slices here...
}
}
Because it is not possible to move out of the slice, the above doesn't work for non-Copy T.
Would it be feasible to enable code like this?
fn f<T>(x: Vec<T>) -> T {
match x { // consumes `x`
[ ... ] // Lots of complicated slices here...
}
}
(I know one can pattern match on tuples from a vec::Drain, but they are only for size up to 4 (why so low?) and require that all patterns have the same length. See a related SO question.)
Do you want items to move? Because your slice pattern can capture just references, explicitly &[ref x, ref y, ..] or implicitly [x, y, ..] with pattern ergonomics.
AFAIK there's no limit to tuple pattern length, but Itertools::tuples() has only implemented lengths up to 4.
For the question of matching Vec -- that's not a special type to the compiler, so I don't think it could get such treatment. However, a Vec<T> can convert to Box<[T]>, and I think you might be able to match that with box [x, y, ..] patterns, though that's an unstable feature.
Hmm, you're right -- while box patterns do allow destructuring moves in general, it seems not for slices. I think it could be allowed though, in theory...
Thanks for the suggestion. I have several large patterns, and it gets a bit verbose. My current choice is the following, but it still feels far from optimal.
fn consume_destructure<T>(x: Vec<T>) -> T {
let mut x = x.into_iter();
match [x.next(), x.next(), x.next(), x.next(), x.next(), x.next()] {
[Some(x), Some(y), Some(z), Some(v), Some(w), None] => {
// Use x, y, z, v, w
},
// Other patterns of varying lengths, with more or less `None`'s
_ => Err(...)
}
}