29

The code below doesn't compile if I uncomment the line indicated. The compiler complains: "stable identifier required".

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")
}

If I assign Stream.empty to value Empty first, it works, but it feels strange that you can't pattern match on such a fundamental value without such a hack.

Am I missing something?

BasilTomato
  • 1,071
  • 1
  • 8
  • 14

2 Answers2

50

You can't pattern match on Stream.empty because it is a method (in object Stream) that always returns the empty stream (but the compiler doesn't know that).

Instead of assigning val empty = Stream.empty, you can match on Stream.Empty, which is an Object :

scala> a match {
           case Stream.Empty => println("done")
           case h #:: tl => println(h)
       }
Marth
  • 23,920
  • 3
  • 60
  • 72
6

You can't "pattern match" on a variable that is not a constant.
Stream.empty is not a "stable" identifier since it represents some method:

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

that could potentially return any value at any time.
Compiler isn't aware that its returned value is always Empty, so it detects it as a potential changing variable.
Too deep for it to detect it.

However, when you assign the method's retult to a val (being a stable identifier since immutable), your code is able to process to pattern matching using it.

You might read this, evoking an hypothesis explaining why pattern matching expects a stable identifier.

Community
  • 1
  • 1
Mik378
  • 21,881
  • 15
  • 82
  • 180