9.3 匹配元组和列表

匹配字面量和枚举很简单。但是,很快我们就会意识到,消息不只有单个的字面量,还有元组或列表形式的一个序列的值。元组和列表也可以用case表达式匹配。假定要编写一个服务,其中需要接收和处理地理坐标。如果将坐标表示成元组,就可以这样匹配:

PatternMatching/MatchTuples.scala

  1. def processCoordinates(input: Any) {
  2. input match {
  3. case (a, b) => printf("Processing (%d, %d)... ", a, b)
  4. case "done" => println("done")
  5. case _ => null
  6. }
  7. }
  8. processCoordinates((39, -104))
  9. processCoordinates("done")

这会匹配了有两个值的任意元组,还有字面量“done”。会得到这样的输出结果:

  1. Processing (39, -104)... done

如果传递的实参不是有两个元素的元组,或不匹配“done”,通配符就会处理它。这里printf()语句有一个隐含的假设,元组里的值是整数。如果不是,代码就会在运行时失败——这可不好。为匹配提供类型信息,可以避免这种情况发生。我们会在9.4节“类型和卫述句的匹配”中看到。

匹配List可以用匹配元组同样的方式。我们只要提供关心的元素即可,剩下的元素可以通过数组展开符(_*)略去。

PatternMatching/MatchList.scala

  1. def processItems(items: List[String]) {
  2. items match {
  3. case List("apple", "ibm") => println("Apples and IBMs")
  4. case List("red", "blue", "white") => println("Stars and Stripes...")
  5. case List("red", "blue", _*) => println("colors red, blue, ... ")
  6. case List("apple", "orange", otherFruits @ _*) =>
  7. println("apples, oranges, and " + otherFruits)
  8. }
  9. }
  10. processItems(List("apple", "ibm"))
  11. processItems(List("red", "blue", "green"))
  12. processItems(List("red", "blue", "white"))
  13. processItems(List("apple", "orange", "grapes", "dates"))

第一个和第二个case分别期望List里有两个和三个特定项。剩下的两个case期待两个或更多的项,但是前两项必须是特定的。如果需要引用余下的匹配项,可以在特殊符号@前放一个变量名(比如otherFruits),正如上面代码所示。输出如下:

  1. Apples and IBMs
  2. colors red, blue, ...
  3. Stars and Stripes...
  4. apples, oranges, and List(grapes, dates)