What is the reasoning behind making ::
specific to List
and not available to all subclasses of Seq
? To give a concrete example:
// :: for pattern matching
def getTail[E](s: Seq[E]): Seq[E] = s match {
case head :: tail => tail
case empty => empty
}
getTail(Seq(1, 2)) // returns List(2) as expected
getTail(Seq()) // returns List() as expected
getTail(Queue(1, 2)) // returns Queue(1, 2), not Queue(2)
getTail(Buffer(1, 2)) // returns ArrayBuffer(1, 2), not ArrayBuffer(2)
// :: for building sequences
1 :: 2 :: 3:: Nil // Creates List(1, 2, 3)
1 :: 2 :: List(3) // same as above
1 :: 2 :: Queue(3) // does not compile. :: is not a method within Queue
All sequences are ordered and have a notion of "head" and "tail," so why did the implementors of the collections library only provide ::
to List
? Why must I use +:
if I want to be able to work with all Seq
?
Edit: I understand the performance argument - I've been given it nearly every time I've asked this question - but I largely disagree with it. Imagine a different collection library where only one thing has been changed: the removal of ::
from List
. What would change?
- I can still build my lists in a performant way using
+:
andNil
such as"A" +: "B" +: Nil
. - I can still elegantly pattern match using
+:
to extract different parts of my list. e.g.case head +: tail => println(head)
- There is a unified method for building and pattern matching all subclasses of
Seq
. This removes the need for a linter to find subtle bugs like the one I've introduced ingetTail
.
I honestly do not see how a method unique to List
makes anything easier, clearer, or more performant than using +:
. And if that is the case, then I see no reason for ::
to be specific to List
. Given this, I don't see the reason for ::
to exist at all.