Search code examples
rustpattern-matchingsliceownership

How can I (slice) pattern match on an owned Vec with non-Copy elements?


My goal is to move elements out of an owned Vec.

fn f<F>(x: Vec<F>) -> F {
    match x.as_slice() {
        &[a, b] => a,
        _ => panic!(),
    }
}

If F is copy, that is no problem as one can simply copy out of the slice. When F is not, slice patterns seem a no-go, as the slice is read only.

Is there such a thing as an "owned slice", or pattern matching on a Vec, to move elements out of x?

Edit: I now see that this code has the more general problem. The function

fn f<T>(x: Vec<T>) -> T {
    x[0]
}

leaves "a hole in a Vec", even though it is dropped right after. This is not allowed. This post and this discussion describe that problem.

That leads to the updated question: How can a Vec<T> be properly consumed to do pattern matching?


Solution

  • If you insist on pattern matching, you could do this:

    fn f<F>(x: Vec<F>) -> F {
        let mut it = x.into_iter();
        match (it.next(), it.next(), it.next()) {
            (Some(x0), Some(_x1), None) => x0,
            _ => panic!(),
        }
    }
    

    However, if you just want to retrieve the first element of a 2-element vector (panicking in other cases), I guess I'd rather go with this:

    fn f<F>(x: Vec<F>) -> F {
        assert_eq!(x.len(), 2);
        x.into_iter().next().unwrap()
    }