使用变量绑定和防护的Scala模式匹配之间的区别

时间:2018-11-07 09:14:24

标签: scala pattern-matching

在进行模式匹配时,在什么情况下需要变量绑定,而防护就不够?

  "hello" match {
    case greeting @ ("yo" | "hello" | "hola") => println(s"greeting is $greeting")
    case _                                    => println("some other greeting")
  }

  "hello" match {
    case greeting if (greeting == "yo" || greeting == "hello" || greeting == "hola") => println(s"greeting is $greeting")
    case _ => println("some other greeting")
  }

这两种方法似乎都可以解决相同的问题。

1 个答案:

答案 0 :(得分:0)

匹配密封性状时,存在巨大差异

sealed trait Option[+A]
case class Some[A](get: A) extends Option[A]
case object None extends Option[Nothing]

val x: Option[String] = ???

通过模式匹配,它很好而且可读:

x match {
  case Some(string) => println("got " + string)
  case None => println("didn't get anything")
}

如果您错过了一个案例,编译器也会发出警告:

x match {
  case Some(string) => println("got " + string)
} // gives you warning that match might fail on None

对于警卫版本,您需要使用强制类型转换,并且对于遗忘的情况没有警告:

x match {
  case some if some.isInstanceOf[Some[_]] =>
    println("got " + some.asInstanceOf[Some[String]].get)
  case none if some == None =>
    println("didn't get anything")
}

此外,当想要检查一层以上的结构时,守卫们很快就会变得丑陋。比较:

case Some(Some(string)) => println(string)

使用

case s if s.isInstanceOf[Some[_]] && s.asInstanceOf[Some[_]].get.isInstanceOf[Some[_]] =>
  println(s.asInstanceOf[Some[_]].get.asInstanceOf[Some[String]].get)