Scala match decomposition on infix operator
Asked Answered
D

3

10

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)?

Dino answered 20/6, 2009 at 18:45 Comment(0)
B
13

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.

Baptiste answered 20/6, 2009 at 20:48 Comment(0)
D
7

I believe :: is actually a class (which is a subclass of List), so saying x :: xs is mostly equivalent to List(x, xs).

You can do this with other case classes that have operator names. For instance:

case class %%%(x: Int, y: Int)

a match {
  case x %%% y => x + y
}
Decant answered 20/6, 2009 at 18:52 Comment(0)
M
4

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

To answer this question:

When seen as a pattern, an infix operation such as p op q is equivalent to op(p, q). That is, the infix operator op is treated as a constructor pattern.

(Programming in Scala, 1st ed., p. 331)

See also scala case classes questions

Mishear answered 19/12, 2010 at 21:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.