Scala's '::' operator, how does it work?

Felix picture Felix · May 13, 2010 · Viewed 24.8k times · Source

In Scala, I can make a caseclass, case class Foo(x:Int), and then put it in a list like so:

List(Foo(42))

Now, nothing strange here. The following is strange to me. The operator :: is a function on a list, right? With any function with one argument in Scala, I can call it with infix notation. An example is 1 + 2 is a function (+) on the object Int. The class Foo I just defined does not have the :: operator, so how is the following possible?

Foo(40) :: List(Foo(2))

In Scala 2.8 RC1, I get the following output from the interactive prompt:

scala> case class Foo(x:Int)
defined class Foo

scala> Foo(40) :: List(Foo(2))
res2: List[Foo] = List(Foo(40), Foo(2))

I can go on and use it, but what is the explanation?

Answer

retronym picture retronym · May 13, 2010

From the Spec:

6.12.3 InfixOperations An infix operator can be an arbitrary identifier. Infix operators have precedence and associativity defined as follows.

...

The associativity of an operator is determined by the operator’s last character. Operators ending in a colon ‘:’ are right-associative. All other operators are left- associative.

You can always see how these rules are applied in Scala by printing the program after it has been through the 'typer' phase of the compiler:

scala -Xprint:typer -e "1 :: Nil"

val r: List[Int] = {
  <synthetic> val x$1: Int = 1;
  immutable.this.Nil.::[Int](x$1)
};