List
有 2 个方法指定用于将元素添加到(不可变)列表:
+:
(实现Seq.+:
),以及::
(仅在List
中定义)
+:
从技术上讲有一个更通用的类型签名 -
def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[List[A], B, That]): That
def ::[B >: A](x: B): List[B]
- 但忽略隐式,根据文档消息,仅需要 That
为 List[B]
,签名是等效的。
List.+:
和 List.::
之间有什么区别?如果它们实际上是相同的,我假设+:
最好避免依赖于具体实现 List
。但是为什么要定义另一个公共(public)方法,以及客户端代码何时调用它?
编辑
模式匹配中还有一个 ::
提取器,但我想知道这些特定的方法。
最佳答案
确定两种方法之间差异的最佳方法是查看源代码。
source ::
:
def ::[B >: A] (x: B): List[B] =
new scala.collection.immutable.::(x, this)
source +:
:
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
参数选择 List.canBuildFrom)。
那么,该使用哪种方法呢?通常人们会选择接口(interface) (+:
) 而不是实现 (::
),但由于 List
是函数式语言中的通用数据结构,因此有自己的方法并被广泛使用。许多算法都是按照 List
的工作方式构建的。例如,您会发现许多方法将单个元素添加到 List
或调用方便的 head
或 tail
方法,因为所有这些操作都是 O(1)
。因此,如果您在本地使用 List
(在单个方法或类内),则选择特定于 List
的方法是没有问题的。但如果你想在类之间进行通信,即你想编写一些接口(interface),你应该选择更通用的 Seq
接口(interface)。
关于list - `::` 和 `+:` 在列表前面有什么区别)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11814675/