
128
CHAPTER 5
■ PATTERN MATCHING
Examining the Internals of Pattern Matching
The next couple of paragraphs get into some gnarly parts of Scala. Let’s write our own
class that is nearly as syntactically pleasing as Scala’s
List. We will rely on a couple of
syntactic features in Scala. The first is that Scala methods and classes can have operator
characters as class names. The following are all valid method and class names:
Foo, Foo_?,
foo32, ?, ?:. The second is that methods that have a colon as their last character are evalu-
ated right to left, rather than left to right. That means
3 :: Nil is desugared to Nil.::(3).
Using these two features of Scala, let’s define our own
MList class that has the same pattern-
matching beauty as Scala’s
List class. The code in this section must be compiled because
there are circular class references. You cannot type this code at the REPL. Here’s the whole
listing:
class MList[+T] {
def ?:[B >: T](x: B): MList[B] = new ?:(x, this)
}
case object MNil extends MList[Nothing]
case class ?:[T](hd: T, tail: MList[T]) extends MList[T]
First, let’s define MList. It has a type of +T, which is part of Scala’s type system, and
it means that subclasses of
MList have a covariant type.
3
Covariant means that T in
subclasses of
MList can be the same class or a superclass of T.
class MList[+T] {
def ?:[B >: T](x: B): MList[B] = new ?:(x, this)
}
MList contains a single method, ?:, which is also the class name of the linked list cons
cell. This allows chaining of constructing lists. Also, note that
B, which is the type of the
parameter, relates to
T using the >: type relationship operator. This means that B must be
the same class or a superclass of
T. So, if you’ve got an MList[String] and you add an Int
cell, the
MList’s type becomes the class that’s the superclass of both: Any. If you have an
MList[Number] and you add an Int, the list is still MList[Number].
Next, let’s define the
MNil singleton. This is an MList[Nothing]. Nothing is the subclass
of every other class.
4
Because MList is covariant, MList[Nothing] can serve as a member of
every
MList. If we’ve got MNil and we call the ?: method with a String, because the super-
class of the two is
String, we add a String cell to MNil resulting in an MList[String].
case object MNil extends MList[Nothing]
3. Covariance and contravariance are scary terms and big concepts. We’ll dive into them in Chapter 7.
4. It works best if you say it out loud.
19897ch05.fm Page 128 Wednesday, April 8, 2009 2:03 PM