Как предотвратить эту ошибку - сопоставление с образцом и Nil - PullRequest
10 голосов
/ 19 февраля 2012

При повторном сопоставлении списков вы можете использовать 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, это не ошибка. И если l имеет тип Set, он не скомпилируется. Но что, если у нас есть класс со списком, определим функцию, которой соответствует шаблон, и затем кто-то изменит класс, чтобы вместо него использовать универсальный итератор? Совпадает ли этот шаблон «ноль против _» с плохой идеей вообще?

Ответы [ 3 ]

12 голосов
/ 19 февраля 2012

Одной из возможностей является использование защиты:

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 (работает лучше всего, если у вас есть только одно или два условия для проверки):

scala> if (xs.isEmpty) 1 else 2
res1: Int = 1
8 голосов
/ 19 февраля 2012

Преобразуйте проверяемого в список, чтобы устранить сомнения.

l.toList match {
  case Nil => 1
  case xs  => 2
}
1 голос
/ 10 мая 2015

Вот еще один вариант (каламбур):

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 и :: завершится неудачей .

Я добавил этот ответ, потому что я думал, что достаточно часто использовать сопоставление с образцом для коллекции, иначе вы можете просто проверить с помощью xs.isEmpty.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...