listscalamatchinfix-operator

Scala match decomposition on infix operator


I'm trying to understand the implementation of Lists in Scala. In particular I'm trying to get my head around how you can write match expressions using an infix operator, for example:

a match {
  case Nil => "An empty list"
  case x :: Nil => "A list without a tail"
  case x :: xs => "A list with a tail"
}

How is the match expression allowed to be x :: xs rather than List(x, xs)?


Solution

  • Jay Conrad's answer is almost right. The important thing is that somewhere there is an object named :: which implements the unapply method, returning type Option[(A, List[A])]. Thusly:

    object :: {
      def unapply[A](ls: List[A]): Option[(A, A)] = {
        if (ls.empty) None
        else Some((ls.head, ls.tail))
      }
    }
    
    // case objects get unapply for free
    case object Nil extends List[Nothing]
    

    In the case of :: and List, this object happens to come out of the fact that :: is a case class which extends the List trait. However, as the above example shows, it doesn't have to be a case class at all.