1
scala> 3 :: List(1,2)
res5: List[Int] = List(3, 1, 2)

scala> 3 +: List(1,2)
res6: List[Int] = List(3, 1, 2)

What's the difference between those two operators?

  • 1
    The same question was answered here: http://stackoverflow.com/questions/11814675/whats-the-difference-between-and-for-prepending-to-a-list?rq=1 – Kipton Barros Mar 06 '13 at 07:58

2 Answers2

7

The difference is that +: is an abstraction of ::, which operates on generalized Seqs rather than only Lists. For instance, +: also works on Streams:

scala> 3 +: Stream(1,2)
res0: scala.collection.immutable.Stream[Int] = Stream(3, ?)

When you use it with a List, it is functionally the same as ::.

Tom Crockett
  • 30,818
  • 8
  • 72
  • 90
  • 1
    So can `::` be deprecated in favor of `+:`, or does it still serve a purpose? – Kipton Barros Mar 06 '13 at 02:50
  • 1
    @KiptonBarros No, because `::` is actually a case class which represents a "constructor" (in the sense of [algebraic data types](http://en.wikipedia.org/wiki/Algebraic_data_type)) for `List`, which means it's absolutely fundamental to the definition of that type. You could perhaps argue that `::` should be hidden and only `+:` should be used by clients, so as to keep one's code as general as possible, but the convention is usually to expose the constructors of an abstract data type which is not likely to change (`List` will never ever change, it is a very clear-cut mathematical object.) – Tom Crockett Mar 06 '13 at 03:08
  • 2
    It might also be worth noting that it's slightly unusual that +: is a function on the object on the right hand side. This is because it ends with a colon--functions that end with : work backwards to how you would expect them to. In the scala collections library, coll :name object is generally the same as object name: coll, except backwards. For example, List(4) :+ 3 == List(4, 3), and 3 +: List(4) == List(3, 4). – nnythm Mar 06 '13 at 05:52
  • 1
    Here the symbol `::` refers to the method defined in the `List` class. In other contexts, `::` could also refer to the case class. – Kipton Barros Mar 06 '13 at 08:11
0

The methods +: and :: defined on the List class have the following implementations,

override def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[List[A], B, That]): That = bf match {
  case _: List.GenericCanBuildFrom[_] => (elem :: this).asInstanceOf[That]
  case _ => super.+:(elem)(bf)
}

def ::[B >: A] (x: B): List[B] =
  new scala.collection.immutable.::(x, this)

The method +: needs to exist because it is inherited from SeqLike. As pelotom says, this is the more general method.

However, I am not sure why the method List.:: needs to exist.

Update: The same question has already been asked. In the comments it is suggested that the method :: exists for historical reasons.

Community
  • 1
  • 1
Kipton Barros
  • 21,002
  • 4
  • 67
  • 80