It's annoying that some of the most visible and awesome features of Scala have so much complexity right beneath the surface. So, consider this simple line:
val (head :: tail): ::[Int] = 1 :: Nil
Each of the three places where ::
appears refers to a different ::
, and a different mechanism in Scala. Let's go through each of them, in order.
head :: tail
What is happening here is pattern matching, just like one sees with case
statements. Pattern matching can appear on val
assignments, on the left side of <-
in for
comprehensions, and on case
statements.
So, how does this particular pattern matching happens? Well, whenever the pattern is in the format a b c
, Scala translates this into b(a, c)
, which is then translated into calls to unapply
or unapplySeq
on the object b
.
So, ::
in val (head :: tail)
refers to the object ::
(defined through a case class
).
: ::[Int]
This is a type declaration, so ::[Int]
is a type. ::
itself is a class, and a type constructor as well (because it constructs types given a type parameter -- ::[Int]
is one type, ::[String]
is another type, etc). It is also a subclass of List
, which has only two subclasses: ::
and the singleton class of Nil
.
This declaration is superfluous, and, generally speaking, one hardly ever uses ::
as a type or class. I show it here mostly for completeness.
1 :: Nil
Here, ::
is a method. It is a method of List
, so, since Nil
is a List
and 1
is not, it must belong to Nil
(or be available through implicit conversion).
The mechanism of note here is that methods ending with :
, when used in infix operator notation, bind to the right instead of to the left. Or, in other words, a :: b
is equivalent to b.::(a)
.
This mechanism is rarely used and, I suspect, made mostly to make traditional fp list algorithms more familiar to programmers used to fp. It is used in a few other places on Scala standard library and out of it.
On Scala 2.8, for instance, there's now +:
, which serves the same purpose of ::
, but is defined for all Seq
. It is mirrored by :+
, which appends elements, and whose :
serves no purpose other than disambiguate it from +
, which is overloaded to concatenate strings.