如何在 Scala 中匹配多个值?

假设我想使用相同的代码处理来自远程服务的多个返回值。我不知道如何在 Scala 中表达:

code match {
case "1" => // Whatever
case "2" => // Same whatever
case "3" => // Ah, something different
}

我知道我可以使用提取方法并调用它,但是在调用中仍然存在重复。如果我用 Ruby,我会这样写:

case code
when "1", "2"
# Whatever
when "3"
# Ah, something different
end

注意,我简化了这个示例,因此我不想在正则表达式或类似的表达式上进行模式匹配。匹配值实际上是复杂的值。

52674 次浏览

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 =>
}

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.