Mec*_*ail 43 scala list operators cons prepend
List
有两个方法指定将元素添加到(不可变)列表:
+:
(实施Seq.+:
),和::
(仅在中定义List
)+:
技术上有一个更通用的类型签名 -
def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[List[A], B, That]): That
def ::[B >: A](x: B): List[B]
Run Code Online (Sandbox Code Playgroud)
-丁忽略隐式的,它根据该文档信息仅需要That
是List[B]
,签名是等效的.
List.+:
和之间有什么区别List.::
?如果它们实际上是相同的,我认为+:
最好避免取决于具体实施List
.但是为什么定义了另一个公共方法,客户端代码何时会调用它?
还有一个用于::
模式匹配的提取器,但我想知道这些特定的方法.
kir*_*uku 36
确定两种方法之间差异的最佳方法是查看源代码.
该源的::
:
def ::[B >: A] (x: B): List[B] =
new scala.collection.immutable.::(x, this)
Run Code Online (Sandbox Code Playgroud)
该源的+:
:
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)
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的那样List
,两种方法都是一样的(编译器会为参数选择List.canBuildFromCanBuildFrom
).
那么,使用哪种方法?通常会选择interface(+:
)而不是implementation(::
),但因为它List
是函数式语言中的通用数据结构,所以它有自己广泛使用的方法.许多算法都是如何构建的List
.例如,您会发现许多方法将单个元素添加到List
或调用方便head
或tail
方法,因为所有这些操作都是O(1)
.因此,如果您在本地使用List
(在单个方法或类中),则选择List
特定方法没有问题.但是如果你想在类之间进行通信,即你想编写一些接口,你应该选择更通用的Seq
接口.
Kim*_*bel 11
+:
更通用,因为它允许结果类型与调用它的对象的类型不同.例如:
scala> Range(1,4).+:(0)
res7: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 1, 2, 3)
Run Code Online (Sandbox Code Playgroud)