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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 01:52:28  来源:igfitidea点击:

What's the difference between `::` and `+:` for prepending to a list)?

listscalaoperatorsprependcons

提问by Mechanical snail

Listhas 2 methods that are specified to prepend an element to an (immutable) list:

List有 2 种方法指定将元素添加到(不可变)列表中:

  • +:(implementing Seq.+:), and
  • ::(defined only in List)
  • +:(实施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 Thatto 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 CanBuildFromargument).

如您所见, for List,两种方法都执行相同的操作(编译器将选择List.canBuildFrom作为CanBuildFrom参数)。

So, which method to use? Normally one would choose the interface (+:) than the implementation (::) but because Listis a general data structure in functional languages it has its own methods which are widely used. Many algorithms are build up the way how Listworks. For example you will find a lot of methods which prepend single elements to Listor call the convenient heador tailmethods 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 Seqinterface.

那么,该使用哪种方法呢?通常人们会选择接口(+:)而不是实现(::),但因为它List是函数式语言中的通用数据结构,它有自己的方法,被广泛使用。许多算法都是按照List工作方式构建的。例如,您会发现许多方法将单个元素添加到List或调用方便的headtail方法,因为所有这些操作都是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)