# Pattern matching in Scala 2.10

One of the improvements that came with Scala 2.10 is completely rewritten and improved pattern matching. In addition to fixing some performance issues (e.g. this exponential space bytecode bug), it fixes a few of the annoyances I’ve had with pattern matching in Scala and gives much more useful errors at compile time.

# Better matching on sequences

Now we can match on Seq more like we match on lists using +: and :+. For example:

def sort[T <% Ordered[T]](seq: Seq[T]): Seq[T] = seq match { case Seq() => Seq() case x +: xs => val (before, after) = xs partition (_ < x) sort(before) ++ sort(x +: after) } sort(IndexedSeq("Greg", "Eishay", "Andrew")) // => List(Andrew, Eishay, Greg)

Since it’s preferred to use the Seq type over List in most places, this should probably be preferred over :: when possible.

Note that xs :+ x captures the last element of the list. You should generally only do this with an IndexedSeq or some other collection that can get the last element efficiently.

# Compile-time checking of type arguments

In 2.9, type arguments would not be checked when destructuring many types. For example, the following code compiles in 2.9:

val (a, b): (Int, Int) = ("a", "b") val List(a, b, c): List[Int] = Some("hello")

The compiler would issue a warning, and then we’d get a ClassCastException when running the code:

val (a, b): (Int, Int) = ("a", "b") :7: warning: non variable type-argument Int in type pattern (Int, Int) is unchecked since it is eliminated by erasure val (a, b): (Int, Int) = ("a", "b") ^ java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer ...

In 2.10, the type checker is smarter, and we get a nice message at compile time:

scala> val (x, y): (Int, Int) = ("a", "b") :7: error: type mismatch; found : String("a") required: Int val (x, y): (Int, Int) = ("a", "b")

# Abstract types

We can also now match on abstract types. So we can do stuff like:

scala> import reflect.ClassTag import reflect.ClassTag scala> def filterBy[T: ClassTag](seq: Seq[Any]) = seq collect { case x: T => x } filterBy: [T](seq: Seq[Any])(implicit evidence\$1: scala.reflect.ClassTag[T])Seq[T] scala> filterBy[String](Seq(1, "two", "three")) res0: Seq[String] = List(two, three)

Note that, unfortunately, we can’t match value types like Int when they are boxed (we have to match the Java wrapper type).

We wrote this post while working on Kifi — Connecting people with knowledge. Learn more.

mslinn

The colors and font for the code examples are hard to read :(