如何防止这种bug - 模式匹配和Nil

dyr*_*oss 10 scala

再次模式匹配列表时,可以使用Nil检查空列表.但是,如果基础类型是Iterable,您仍然可以检查Nil,它将为空集等中断...请参阅以下REPL会话:

scala> val l: Iterable[Int] = List()
l: Iterable[Int] = List()

scala> l match {
     | case Nil => 1
     | case _ => 2
     | }
res0: Int = 1

scala> val l: Iterable[Int] = Set() 
l: Iterable[Int] = Set()

scala> l match {
     | case Nil => 1
     | case _ => 2
     | }
res2: Int = 2
Run Code Online (Sandbox Code Playgroud)

问题是 - 我该如何防止这类问题?显然,如果l是类型List,那就不是bug.如果l的类型为Set,则不会编译.但是,如果我们有一个具有列表的类,定义一个模式以这种方式匹配的函数,然后有人改变该类以采用通用迭代呢?这种Nil vs. _模式总体上是一个坏主意吗?

kir*_*uku 12

一种可能性是使用警卫:

scala> val xs: Iterable[Int] = Set()
xs: Iterable[Int] = Set()

scala> xs match { case xs if xs.isEmpty => 1 case _ => 2 }
res0: Int = 1
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用if-else-expression(如果你只有一个或两个条件要检查,效果最好):

scala> if (xs.isEmpty) 1 else 2
res1: Int = 1
Run Code Online (Sandbox Code Playgroud)


ret*_*nym 8

将scrutinee转换为列表以消除疑虑.

l.toList match {
  case Nil => 1
  case xs  => 2
}
Run Code Online (Sandbox Code Playgroud)