list `::` 和 `+:` 之间的区别是什么用于添加到列表中)?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11814675/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What's the difference between `::` and `+:` for prepending to a list)?
提问by Mechanical snail
List
has 2 methods that are specified to prepend an element to an (immutable) list:
List
有 2 种方法指定将元素添加到(不可变)列表中:
+:
(implementingSeq.+:
), and::
(defined only inList
)
+:
(实施Seq.+:
),和::
(仅在 中定义List
)
+:
technically has a more general type signature—
+:
技术上有一个更通用的类型签名——
def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[List[A], B, That]): That
def ::[B >: A](x: B): List[B]
—but ignoring the implicit, which according to the doc message merely requires That
to be List[B]
, the signatures are equivalent.
- 但忽略隐式,根据 doc 消息只需That
要是List[B]
,签名是等效的。
What is the difference between List.+:
and List.::
?If they are in fact identical, I assume +:
would be preferred to avoid depending on the concrete implementation List
. But why was another public method defined, and when would client code call it?
List.+:
和 和有List.::
什么区别?如果它们实际上相同,我认为+:
最好根据具体实现避免List
。但是为什么要定义另一个公共方法,客户端代码什么时候调用它?
Edit
编辑
There is also an extractor for ::
in pattern matching, but I'm wondering about these particular methods.
还有一个用于::
模式匹配的提取器,但我想知道这些特定的方法。
See also: Scala list concatenation, ::: vs ++
另请参阅:Scala 列表连接,::: vs ++
采纳答案by kiritsuku
The best way to determine the difference between both methods is to look it the source code.
确定两种方法之间差异的最佳方法是查看源代码。
The sourceof ::
:
该源的::
:
def ::[B >: A] (x: B): List[B] =
new scala.collection.immutable.::(x, this)
The sourceof +:
:
该源的+:
:
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)
}
As you can see, for List
, both methods do one and the same (the compiler will choose List.canBuildFromfor the CanBuildFrom
argument).
如您所见, for List
,两种方法都执行相同的操作(编译器将选择List.canBuildFrom作为CanBuildFrom
参数)。
So, which method to use? Normally one would choose the interface (+:
) than the implementation (::
) but because List
is a general data structure in functional languages it has its own methods which are widely used. Many algorithms are build up the way how List
works. For example you will find a lot of methods which prepend single elements to List
or call the convenient head
or tail
methods because all these operations are O(1)
. Therefore, if you work locally with a List
(inside of single methods or classes), there is no problem to choose the List
-specific methods. But if you want to communicate between classes, i.e. you want to write some interfaces, you should choose the more general Seq
interface.
那么,该使用哪种方法呢?通常人们会选择接口(+:
)而不是实现(::
),但因为它List
是函数式语言中的通用数据结构,它有自己的方法,被广泛使用。许多算法都是按照List
工作方式构建的。例如,您会发现许多方法将单个元素添加到List
或调用方便的head
或tail
方法,因为所有这些操作都是O(1)
. 因此,如果您在本地使用 a List
(在单个方法或类中),则选择List
特定方法没有问题。但是如果你想在类之间进行通信,即你想写一些接口,你应该选择更通用的Seq
接口。
回答by Kim Stebel
+:
is more generic, since it allows the result type to be different from the type of the object it is called on. For example:
+:
更通用,因为它允许结果类型与调用它的对象的类型不同。例如:
scala> Range(1,4).+:(0)
res7: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 1, 2, 3)