使::
特定于List
而不能用于Seq
的所有子类的原因是什么?给出一个具体的例子:
// :: 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
所有序列都是有序的,并且有"头"one_answers"尾"的概念,那么为什么集合库的实现者只提供::
到List
呢?如果我想能够使用所有Seq
,为什么我必须使用+:
?
编辑:我理解关于性能的争论——几乎每次我问这个问题的时候都有人这样问我——但我很大程度上不同意它。想象一个不同的集合库,其中只更改了一件事:从List
中删除了::
。什么会改变?
- 我仍然可以使用
+:
和Nil
(如"A" +: "B" +: Nil
)以高性能的方式构建我的列表。 - 我仍然可以使用
+:
优雅的模式匹配来提取我的列表的不同部分。例:case head +: tail => println(head)
-
Seq
的所有子类都有统一的构建和模式匹配方法。这样就不需要linter来查找像我在getTail
中介绍的那种细微的bug。
老实说,我看不出List
独有的方法如何比使用+:
更容易、更清晰或更高效。如果是这样的话,那么我认为::
没有理由特定于List
。考虑到这一点,我看不出::
存在的理由。
与所有类特定操作符背后的原因相同。如#::
对应Stream
, !
对应Actor
。
由于List
是单链的,所以在O(1)中进行前置元素和解构为头+尾。它基本上是列表中最常用的操作。List的整个思想就是围绕这个操作构建的。
请注意,List
也支持Seq
的+:
。但是使用::
清楚地表明您打算以有效的方式使用List
。