List 为什么::仅适用于列表?

List 为什么::仅适用于列表?,list,scala,collections,cons,List,Scala,Collections,Cons,使:特定于列表而不适用于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

使
特定于
列表而不适用于
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
所有序列都是有序的,并且都有“头”和“尾”的概念,那么为什么集合库的实现者只向
列表提供
?如果我想处理所有的
序列
,为什么我必须使用
+:

编辑:我理解性能论证——几乎每次我问这个问题时都会得到它——但我基本上不同意它。想象一个不同的集合库,其中只有一件事被更改:从
列表中删除
。什么会改变

  • 我仍然可以使用
    +:
    Nil
    以高效的方式构建列表,例如
    “a”+:“B”+:Nil
  • 我仍然可以使用
    +:
    优雅地进行模式匹配,以提取列表的不同部分。e、 g.
    case head+:tail=>println(head)
  • 有一种统一的方法来构建和模式匹配
    Seq
    的所有子类。这样就不需要使用linter来查找细微的bug,就像我在
    getTail
    中介绍的那样

老实说,我不知道
List
特有的方法如何比使用
+:
更容易、更清晰或更高效。如果是这样的话,那么我认为没有理由将
特定于
列表。有鉴于此,我根本看不出
存在的原因。

所有特定于类的运算符背后都有相同的推理。像
#::
用于
Actor

由于
列表
是单链接的,所以在O(1)中预加元素并解构为head+tail。它基本上是列表最常用的操作。列表的整个概念都是围绕这个操作构建的


请注意,
List
也支持
Seq
+:
。但是使用
清楚地表明了您打算以有效的方式使用
列表。

这已经够让人困惑的了,他们需要lint规则来防范它。但并不是每个seq都有一个有效的尾部(如果需要分配的话)。我认为它的存在是为了让::unapply/提取器更有效。这意味着::(作为cons)只是为了对称。@TheArchetypalPaul使
案例类与所有
Seq
一起工作,而不仅仅是
列表
,这很简单。对于
列表
,提取器仍然是有效的,不是吗?我已经通过编辑我的问题回答了这个问题。我不认为性能是拥有
的正当理由,因为
+:
有着相同的目的,同样的性能,并且可以被
的所有子类使用。