【发布时间】:2016-01-23 09:30:45
【问题描述】:
使:: 特定于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
所有序列都是有序的,并且有“头”和“尾”的概念,那么为什么集合库的实现者只提供:: 到List?如果我希望能够使用所有Seq,为什么必须使用+:?
编辑:我理解性能论点 - 几乎每次我问这个问题时都会得到它 - 但我在很大程度上不同意它。想象一个不同的集合库,其中只有一件事发生了变化:从List 中删除::。会发生什么变化?
- 我仍然可以使用
+:和Nil(例如"A" +: "B" +: Nil)以高效的方式构建我的列表。 - 我仍然可以优雅地使用
+:进行模式匹配,以提取列表的不同部分。例如case head +: tail => println(head) - 有一个统一的方法来构建和模式匹配
Seq的所有子类。这样就无需使用 linter 来查找我在getTail中介绍的细微错误。
老实说,我看不出List 独有的方法如何比使用+: 更容易、更清晰或更高效。如果是这种情况,那么我认为:: 没有理由特定于List。鉴于此,我根本看不出:: 存在的原因。
【问题讨论】:
-
这太令人困惑了,他们需要 lint 规则来防范它。但并非每个 seq 都有有效的尾部(如果需要分配)。
-
我认为它就在那里,所以 :: unapply / extractor 可以很有效。这意味着 :: (as cons) 只是为了对称。
-
@TheArchetypalPaul 让
::case 类与所有Seq一起工作是微不足道的,而不仅仅是List。提取器对List仍然有效,不是吗?
标签: list scala collections cons