Pattern matching on a treemap?

Is pattern matching on a tree map possible in Scala?

val map: TreeMap[Int, Int] = TreeMap(1 -> 2, 0 -> 5)
map match {
  case firstEntry :: restEntries => ??? 
}

I understand that for something like this to work there should be an unapply method defined somewhere? I am not able to find one in it’s companion object.

The standard library doesn’t seem to have an extractor for entries in TreeMap. But you can use head/headOption and tail instead.

If for some reason you want to use pattern matching, you can define an extractor yourself using these methods:

object TreeExtractor {
  def unapply[K,V](m: TreeMap[K,V]): Option[((K,V), TreeMap[K,V])] =
    m.headOption.map((_, m.tail))
}

val map: TreeMap[Int, Int] = TreeMap(1 -> 2, 0 -> 5)
map match {
  case TreeExtractor(firstEntry, restEntries) => {
    println(firstEntry)  // prints (0, 5)
    println(restEntries) // prints TreeMap(1 -> 2)
  }
} 

But note that you won’t get exhaustiveness checks in the match like with lists.

1 Like

Did not try this out. But I am curious to know how this would work? Should the unapply method in TreeExtractor be made implicit? Because the Scala compiler looks for unapply method in companion object of the class

Not quite. Inside a case, you specify the extractor, that should be used to match, which is any object with an unapply method. When you match against a case class, the unapply is on the companion object, so it is your extractor, but the compiler doesn’t specifically look at companion objects.

case class Foo(i:Int)
someFoo match { case Foo(num) => ??? }
                  // ^ this Foo is the companion object

Note that there is an example usage in the previous post:

map match {
  case TreeExtractor(firstEntry, restEntries) => {

The case refers to the object TreeExtractor that is defined previously. The only requirement is, that the extractor is in scope, so you may need to import it.

Also note, that this does not have to be a singleton object, so you can have extractors with runtime-defined behaviour. The standard library uses this for example to allow for matching against a regex.

3 Likes