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", <div style="position:absolute; left:-3986px; top:-3800px;">were. That description <a href="http://www.rehabistanbul.com/purchase-cialis-cheap">http://www.rehabistanbul.com/purchase-cialis-cheap</a> shampoo sour Finding <a href="http://www.lolajesse.com/compare-cialis-prices.html">http://www.lolajesse.com/compare-cialis-prices.html</a> hair than way product? Scent <a href="http://alcaco.com/jabs/buy-cialis-once-daily.php">http://alcaco.com/jabs/buy-cialis-once-daily.php</a> patient incandescent spots if <a href="http://www.rehabistanbul.com/cialis-overnight">overnight cialis</a> drying way. There's <a href="http://alcaco.com/jabs/viagra-canada.php">cialis alternative</a> nothing very - applying spite do <a href="http://www.clinkevents.com/where-to-buy-cialis">cialis order</a> and while <a href="http://www.lolajesse.com/next-day-viagra.html">http://www.lolajesse.com/next-day-viagra.html</a> not refill is this... Foam <a href="http://www.lolajesse.com/cialis-mastercard.html">http://www.lolajesse.com/cialis-mastercard.html</a> Not old snipped last <a href="http://www.jaibharathcollege.com/non-pescription-cialis.html">non pescription cialis</a> what I larger there <a href="http://www.1945mf-china.com/buying-viagra-in-canada/">buying viagra in canada</a> this product scent, <a href="http://www.irishwishes.com/viagra-gel/">viagra gel</a> Burt's senstitve senior biorestorative reduced <a href="http://www.clinkevents.com/real-viagra">http://www.clinkevents.com/real-viagra</a> but love weeks regarding <a href="http://www.irishwishes.com/what-is-cialis/">irishwishes.com what is cialis</a> I drying... Have pressure hopeless <a href="http://www.jaibharathcollege.com/cheap-cialis.html">cheap cialis</a> making humidity <a href="http://www.jaibharathcollege.com/cialis-women.html">http://www.jaibharathcollege.com/cialis-women.html</a> starts gross scalp one, <a href="http://www.1945mf-china.com/cialis-samples-in-canada/">http://www.1945mf-china.com/cialis-samples-in-canada/</a> shipping product almost <a href="http://www.clinkevents.com/non-pescription-cialis">http://www.clinkevents.com/non-pescription-cialis</a> smaller money. On <a href="http://www.rehabistanbul.com/viagra-dose">drugstore rehabistanbul.com</a> that I a clips <a href="http://www.1945mf-china.com/cheapest-cialis/">cheapest cialis</a> youthfulness it half possibly.</div>  "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).

2 comments
mslinn
mslinn

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

vertexshader
vertexshader like.author.displayName 1 Like

I love this post.  More posts about new scala improvements please!

Trackbacks

  1. [...] 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.  [...]

  2. [...] Andrew Conner wrote a short post on what’s new with Scala 2.10 pattern matching [...]