This is counter intuitive since if infix operators are read left to
right
If you think about it, logically, it makes much sense. The ::
(cons) operator prepends the value to the beginning of the list, it doesn't append it to the end of the list. When you think about it like that, the fact that the ::
operator is right associative makes sense, as it is sticking an element to the beginning of the List
:
scala> 4 :: List(3,2,1)
res1: List[Int] = List(4, 3, 2, 1)
The internal implementation is rather simple:
def ::[B >: A] (x: B): List[B] =
new scala.collection.immutable.::(x, this)
List
is internally implemented as a LinkedList which contains a head which is the first element in the collection, and a list of remaining elements which are the tail. That is why prepending the element is much cheaper than appending it, as it would require an O(n) traversal of the internal list in order to copy the elements, plus appending of the new value.
Although expensive, you can still do it using the :+
operator, which is left associative:
scala> List(1,2,3) :+ 4
res3: List[Int] = List(1, 2, 3, 4)