How to pattern match multiple values in Scala?

Solution 1:

You can do:

code match {
  case "1" | "2" => // whatever
  case "3" =>
}

Note that you cannot bind parts of the pattern to names - you can't do this currently:

code match {
  case Left(x) | Right(x) =>
  case null =>
}

Solution 2:

The other answer correctly says that currently there is no way to pattern-match multiple alternatives while extracting values at the same time. I'd like to share a coding pattern with you that comes close to doing this.

Scala allows you to pattern-match alternatives without extracting values, e.g. case Dog(_, _) | Cat(_, _) => ... is legal. Using this, you can simply extract the values yourself within the case block.

Here's a somewhat contrived example:

abstract class Animal
case class Dog(age: Int, barkLevel: Int) extends Animal
case class Cat(apparentAge: Int, cutenessLevel: Int) extends Animal

val pet: Animal = Dog(42, 100)

// Assume foo needs to treat the age of dogs and the apparent age
// of cats the same way.
// Same holds for bark and cuteness level.
def foo(pet: Animal): Unit = pet match {
  case animal@(Dog(_, _) | Cat(_, _)) =>

    // @unchecked suppresses the Scala warning about possibly
    // non-exhaustiveness even though this match is exhaustive
    val (agelike, level) = (animal: @unchecked) match {
      case Dog(age, barkLevel) => (age, barkLevel)
      case Cat(apparentAge, cutenessLevel) => (apparentAge, cutenessLevel)
    }

    ???
}

Assume that ??? actually stands for doing something that is equal for dogs and cats. Without this coding pattern, you would need to have two cases, one for dogs and one for cats, forcing you to duplicate code or at least to outsorce code into a function.

Generally, the coding pattern above is suitable if you have sibling case classes that share fields that behave identically only for some algorithms. In those cases, you cannot extract those fields to a common superclass. Still, you would like to pattern-match in a uniform way on those fields in the algorithms that treat them equally. This you can do as shown above.