2

In scala repl

scala> List(1) :: 2
<console>:8: error: value :: is not a member of Int
          List(1) :: 2

but

scala> 2 :: List(1);
res4: List[Int] = List(2, 1)

This is counter intuitive since if infix operators are read left to right, the above line can be translate to

List(1) :: 2
List(1).::(2) 

and

2 :: List(1)
2.::(List(1))

I would imagine an Int does not have method :: while a List does. Am I assuming something wrong?

Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
Kevin
  • 2,187
  • 4
  • 26
  • 35
  • 1
    Possible duplicate of [What good are right-associative methods in Scala?](http://stackoverflow.com/questions/1162924/what-good-are-right-associative-methods-in-scala) – Jörg W Mittag Mar 21 '16 at 01:00

2 Answers2

3

Scala operators that end in : are right-associative. So, in your example, you are trying to apply the :: operator to an Int.

Also, List structures are immutable in Scala, so appending to the end of a list is quite expensive; prepending a value to the beginning of a list is very cheap.

Bob Dalgleish
  • 8,167
  • 4
  • 32
  • 42
3

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)
Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321