简体   繁体   English

在列表前加上`::`和`+:`之间有什么区别?

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

List has 2 methods that are specified to prepend an element to an (immutable) list: List有2个方法,用于将元素添加到(不可变)列表中:

  • +: (implementing Seq.+: ), and +:实现Seq.+: ,和
  • :: (defined only in List ) :: :(仅在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. -丁忽略隐式的,它根据该文档信息仅需要ThatList[B]所述签名是等效的。

What is the difference between List.+: and List.:: ? List.+:List.:: ?之间有什么区别? If they are in fact identical, I assume +: would be preferred to avoid depending on the concrete implementation List . 如果它们实际上是相同的,我假设+:最好避免取决于具体的实现List But why was another public method defined, and when would client code call it? 但是为什么定义了另一个公共方法,客户端代码何时会调用它?

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 list concatenation,::: vs ++

The best way to determine the difference between both methods is to look it the source code. 确定两种方法之间差异的最佳方法是查看源代码。

The source of :: : ::来源

def ::[B >: A] (x: B): List[B] =
  new scala.collection.immutable.::(x, this)

The source of +: : +:来源

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.canBuildFrom for the CanBuildFrom argument). 如您所见,对于List ,两种方法都是一样的(编译器将为CanBuildFrom参数选择List.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. 通常会选择接口( +: ::而不是实现( ::但由于List是函数式语言中的通用数据结构,因此它有自己广泛使用的方法。 Many algorithms are build up the way how List works. 许多算法都是List工作方式的基础。 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) . 例如,您会发现许多方法将单个元素添加到List或调用方便的headtail方法,因为所有这些操作都是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. 因此,如果您在本地使用List (在单个方法或类中),则选择List -specific特方法没有问题。 But if you want to communicate between classes, ie you want to write some interfaces, you should choose the more general Seq interface. 但是如果你想在类之间进行通信,即你想编写一些接口,你应该选择更通用的Seq接口。

+: 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM