`::`和`+:`之间有什么区别?
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)