Single level match on Vector?

pub enum Animal {
  Cat(i64),
  Dog(String)
}

pub enum Object {
  Foo(i32),
  Animals(Vec<Animal>
}

Now, to do match, I need to do something like:

let x: Object;

match x {
  Animals(v) => {
    match v.as_slice() {
      [Cat(c), Dog(d)] => { ... }
      _ => {}
    ?
  _ => {}
}

Now, this results in two levels of match. Is there a way to eliminate one of the two?

In general you can match nested enums with destructuring syntax: https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html#destructuring-nested-structs-and-enums

In this specific case, you cannot. This is because you need a temporary binding to take a slice from the embedded Vec. What you can do though, is simplify this trivial example with nested if-let expressions:

if let Animals(v) = x {
    if let [Cat(c), Dog(d)] = v.as_slice() {
        println!("Got animals: {:?}, {:?}", c, d);
    }
}

Playground

1 Like

I think I’m missing something – what is the advantage of "2 levels of if-let’ over “2 levels of match” ?

It saves one level of indentation.

The same unfortunate issue also prevents matching through Boxes without the nightly box keyword, and through any other smart pointer regardless.

I’m hoping for a “match ergonomics part 2” proposal to address that…

3 Likes