How to match with vector element in Rust?

Viewed 5352

In Rust, matching a value like this works:

let x = 1;

match x {
    1 => println!("one"),
    2 => println!("two"),
    _ => println!("something else")
}

But using values from a vector instead of hard-coded numbers in match doesn't work:

let x = 1;
let list = vec![1, 2];

match x {
    list[0] => println!("one"),
    list[1] => println!("two"),
    _ => println!("something else")
}

This fails with the message:

error: expected one of `=>`, `@`, `if`, or `|`, found `[`
 --> src/main.rs:6:9
  |
6 |     list[0] => println!("one"),
  |         ^ expected one of `=>`, `@`, `if`, or `|` here

Why doesn't it work?

1 Answers

The pattern of a match arm is defined as

Syntax
Pattern :
     LiteralPattern
   | IdentifierPattern
   | WildcardPattern
   | RangePattern
   | ReferencePattern
   | StructPattern
   | TupleStructPattern
   | TuplePattern
   | GroupedPattern
   | SlicePattern
   | PathPattern
   | MacroInvocation

It's either constant (including literal) or structural, not computed. A value defined as list[0] matches none of those definitions.

Fortunately, a match arm may also contain a guard expression, which allows for this:

let x = 1;
let list = vec![1, 2];

match x {
    _ if x == list[0] => println!("one"),
    _ if x == list[1] => println!("two"),
    _ => println!("something else")
}

Using if else would be cleaner, though (or a different structure if you have more cases, like a map, or the index).

Related