Подтвердить что ты не робот

Почему я не могу сопоставить шаблон по Stream.empty в Scala?

Код ниже не компилируется, если я раскомментировал указанную строку. Компилятор жалуется: "требуется стабильный идентификатор".

val Empty = Stream.empty    
val a = Stream.range(0, 5)
a match {
  // case Stream.empty => println("nope") <-- does not work
  case Empty => println("compiles") <-- works
  case _ => println("ok")
}

Если я сначала присваиваю Stream.empty значение Empty, это работает, но странно, что вы не можете сопоставить образ с таким фундаментальным значением без такого взлома.

Я что-то пропустил?

4b9b3361

Ответ 1

Вы не можете сопоставить образ на Stream.empty, потому что это метод (в объекте Stream), который всегда возвращает пустой поток (но компилятор этого не знает).

Вместо назначения val empty = Stream.empty вы можете сопоставлять Stream.empty, который является Object:

scala> a match {
           case Stream.Empty => println("done")
           case h #:: tl => println(h)
       }

Ответ 2

Вы не можете "сопоставить шаблон" с переменной , которая не является константой.
Stream.empty не является "стабильным" идентификатором, поскольку он представляет некоторый метод:

/** The empty stream */
  override def empty[A]: Stream[A] = Empty

который потенциально может вернуть любое значение в любое время.
Компилятор не знает, что его возвращаемое значение всегда Empty, поэтому оно обнаруживает его как потенциальную переменную .
Слишком глубоко, чтобы это обнаружить.

Однако, когда вы назначаете метод retult на val (являющийся стабильным идентификатором с неизменяемым), ваш код может обрабатывать его с помощью шаблона.

Вы можете прочитать this, вызывая гипотезу, объясняющую, почему соответствие шаблонов ожидает стабильного идентификатора.