再次模式匹配列表时,可以使用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
问题是 - 我该如何防止这类问题?显然,如果l是类型List,那就不是bug。如果l的类型为Set,则不会编译。但是,如果我们有一个具有列表的类,定义一个模式以这种方式匹配的函数,然后有人改变该类以采用通用迭代呢?这种Nil vs. _模式一般来说是个坏主意吗?
答案 0 :(得分: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
另一种方法是使用if-else-expression(如果你只有一个或两个条件要检查,效果最好):
scala> if (xs.isEmpty) 1 else 2
res1: Int = 1
答案 1 :(得分:8)
将scrutinee转换为列表以消除疑虑。
l.toList match {
case Nil => 1
case xs => 2
}
答案 2 :(得分:1)
这是另一种选择(双关语):
scala> val l: Iterable[Int] = List()
l: Iterable[Int] = List()
scala> l.headOption match { case None => 1; case Some(h) => 2 }
res0: Int = 1
这适用于模式匹配以便在热门head
中获得List() match { case h :: t => ... }
的情况,但它不是列表,而是Iterable
和 {{1将失败。
我添加了这个答案,因为我认为对一个集合进行模式匹配是很常见的,否则你只需要查看::
。