`::`和`+:`之间有什么区别?
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或者调用方便的head或tail方法,因为所有这些操作都是O(1) 。 因此,如果您在本地使用List (在单个方法或类中),则selectList特定方法没有任何问题。 但是如果你想在类之间进行通信,即你想写一些接口,你应该select更通用的Seq接口。
+:更通用,因为它允许结果types与被调用的对象的types不同。 例如:
scala> Range(1,4).+:(0) res7: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 1, 2, 3)