Я не могу найти что-либо в спецификации языка в отношении пунктов недостижимого соответствия. Кто-нибудь поправит меня, если я ошибаюсь.
Итак, я предполагаю, что недостижимые ошибки компиляции основаны на максимальных усилиях, что может объяснить, почему в первом случае нет жалоб.
scala -Xprint:typer
предполагает, что Nil
является буквенным шаблоном , использующим immutable.this.Nil.==
для проверки на совпадение, в то время как List()
является шаблоном экстрактора . Глядя на реализацию экстрактора в нем, похоже, делает что-то вроде this :
def unapplySeq[A](x: CC[A]): Some[CC[A]] = Some(x)
Так что мне стало любопытно и выкатили альтернативную реализацию:
object ListAlt {
def unapplySeq[A](l: List[A]): Some[List[A]] = Some(l)
}
Это соответствует List()
:
scala> Nil match { case ListAlt() => 1 }
res0: Int = 1
Но если я реализую вашу функцию с ней, она прекрасно скомпилируется (за исключением непроверенного предупреждения):
def f(a: Any) = a match { case ListAlt() => 1 case Nil => 2 case _ => 0 }
scala> f(List())
res2: Int = 1
scala> f(Nil)
res3: Int = 1
scala> f(4)
res4: Int = 0
Поэтому мне интересно, есть ли в реализации средства сопоставления с образцом какой-то специальный регистр для Nil
и List()
. Может быть, он обрабатывает List () как литерал ...