`::`和`+:`之间有什么区别?

List有两个方法被指定将一个元素预先添加到一个(不可变的)列表中:

  • +:实施Seq.+:
  • :: :(仅在List定义)

+:技术上具有更一般的types签名 –

 def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[List[A], B, That]): That def ::[B >: A](x: B): List[B] 

– 但是忽略隐含的,根据文档消息只要求List[B] ,签名是等价的。

List.+:List.:: ?有什么区别? 如果它们实际上是相同的,那么我认为+:会避免依赖具体的实现List 。 但为什么又定义了另一个公共方法,客户端代码何时会调用它?

编辑

还有一个::模式匹配提取器,但我想知道这些特定的方法。

另请参见: Scala列表连接,::: vs ++

确定两种方法之间差异的最好方法是将其看作源代码。

::的来源 :

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

+:的来源

 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) } 

正如你所看到的,对于List ,两个方法都是一样的(编译器会为CanBuildFrom参数selectList.canBuildFrom )。

那么,使用哪种方法? 通常情况下,人们会select接口( +: ::而不是实现( ::但是因为List是函数式语言中的一般数据结构,所以它有自己的被广泛使用的方法。 许多algorithm是按照List工作方式构build的。 例如,你会发现很多方法将单个元素添加到List或者调用方便的headtail方法,因为所有这些操作都是O(1) 。 因此,如果您在本地使用List (在单个方法或类中),则selectList特定方法没有任何问题。 但是如果你想在类之间进行通信,即你想写一些接口,你应该select更通用的Seq接口。

+:更通用,因为它允许结果types与被调用的对象的types不同。 例如:

 scala> Range(1,4).+:(0) res7: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 1, 2, 3)