"::"和"+:"之间有什么区别,用于列表的前缀)?



List有两个方法,它们被指定为将元素前置到(不可变)列表:

  • +:(实现Seq.+:),以及
  • ::(仅在List中定义)

+:在技术上有一个更通用的类型签名——

def +:[B >: A, That](elem: B)(implicit bf: CanBuildFrom[List[A], B, That]): That
def ::[B >: A](x: B): List[B]

--但忽略隐式,根据doc消息,隐式仅要求ThatList[B],签名是等效的。

List.+:List.::之间有什么区别如果它们实际上是相同的,我认为+:最好避免,这取决于具体的实现List。但是,为什么要定义另一个公共方法,客户端代码什么时候会调用它呢?

编辑

模式匹配中还有一个::的提取器,但我想知道这些特定的方法。

另请参阅:Scala列表串联,::vs++

确定两种方法之间差异的最佳方法是查看源代码。

::的来源:

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

+:的来源:

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)。

那么,该使用哪种方法呢?通常,人们会选择接口(+:)而不是实现(::),但由于List是函数语言中的通用数据结构,它有自己的方法,这些方法被广泛使用。许多算法都是以CCD_ 21的工作方式构建的。例如,您会发现许多方法将单个元素前置到List,或者调用方便的headtail方法,因为所有这些操作都是O(1)。因此,如果您在本地使用List(在单个方法或类内部),那么选择List特定的方法是没有问题的。但是,如果你想在类之间进行通信,即你想编写一些接口,你应该选择更通用的Seq接口。

+:更通用,因为它允许结果类型与调用对象的类型不同。例如:

scala> Range(1,4).+:(0)
res7: scala.collection.immutable.IndexedSeq[Int] = Vector(0, 1, 2, 3)

相关内容

  • 没有找到相关文章

最新更新