list Scala 列表连接,::: vs ++

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6559996/
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:40:51  来源:igfitidea点击:

Scala list concatenation, ::: vs ++

listscalaconcatenation

提问by Luigi Plinge

Is there any difference between :::and ++for concatenating lists in Scala?

Scala 中的连接列表:::++连接列表之间有什么区别吗?

scala> List(1,2,3) ++ List(4,5)
res0: List[Int] = List(1, 2, 3, 4, 5)

scala> List(1,2,3) ::: List(4,5)
res1: List[Int] = List(1, 2, 3, 4, 5)

scala> res0 == res1
res2: Boolean = true

From the documentationit looks like ++is more general whereas :::is List-specific. Is the latter provided because it's used in other functional languages?

文档来看它看起来++更通用,而:::List具体。提供后者是因为它在其他函数式语言中使用吗?

采纳答案by Daniel C. Sobral

Legacy. List was originally defined to be functional-languages-looking:

遗产。List 最初被定义为看起来像函数式语言:

1 :: 2 :: Nil // a list
list1 ::: list2  // concatenation of two lists

list match {
  case head :: tail => "non-empty"
  case Nil          => "empty"
}

Of course, Scala evolved other collections, in an ad-hoc manner. When 2.8 came out, the collections were redesigned for maximum code reuse and consistent API, so that you can use ++to concatenate anytwo collections -- and even iterators. List, however, got to keep its original operators, aside from one or two which got deprecated.

当然,Scala 以一种特别的方式发展了其他集合。当 2.8 出现时,集合被重新设计以实现最大的代码重用和一致的 API,以便您可以使用++连接任何两个集合——甚至迭代器。但是,List 必须保留其原始运算符,除了一两个已弃用的运算符。

回答by ZhekaKozlov

Always use :::. There are two reasons: efficiency and type safety.

始终使用:::. 有两个原因:效率和类型安全。

Efficiency

效率

x ::: y ::: zis faster than x ++ y ++ z, because :::is right associative. x ::: y ::: zis parsed as x ::: (y ::: z), which is algorithmically faster than (x ::: y) ::: z(the latter requires O(|x|) more steps).

x ::: y ::: z比 快x ++ y ++ z,因为:::是右结合。x ::: y ::: z被解析为x ::: (y ::: z),这在算法上比(x ::: y) ::: z(后者需要 O(|x|) 更多步)更快。

Type safety

类型安全

With :::you can only concatenate two Lists. With ++you can append any collection to List, which is terrible:

随着:::你只能连接两个List秒。随着++您可以附加任何集合List,这是可怕的:

scala> List(1, 2, 3) ++ "ab"
res0: List[AnyVal] = List(1, 2, 3, a, b)

++is also easy to mix up with +:

++也很容易与+

scala> List(1, 2, 3) + "ab"
res1: String = List(1, 2, 3)ab

回答by paradigmatic

:::works only with lists, while ++can be used with any traversable. In the current implementation (2.9.0), ++falls back on :::if the argument is also a List.

:::仅适用于列表,而++可用于任何可遍历的。在当前的实现(2.9.0),++倒在:::如果参数也是List

回答by Mika?l Mayer

A different point is that the first sentence is parsed as:

不同的一点是,第一句话被解析为:

scala> List(1,2,3).++(List(4,5))
res0: List[Int] = List(1, 2, 3, 4, 5)

Whereas the second example is parsed as:

而第二个示例被解析为:

scala> List(4,5).:::(List(1,2,3))
res1: List[Int] = List(1, 2, 3, 4, 5)

So if you are using macros, you should take care.

所以如果你使用宏,你应该小心。

Besides, ++for two lists is calling :::but with more overhead because it is asking for an implicit value to have a builder from List to List. But microbenchmarks did not prove anything useful in that sense, I guess that the compiler optimizes such calls.

此外,++两个列表正在调用,:::但开销更多,因为它要求隐式值以拥有从列表到列表的构建器。但是在这个意义上,微基准测试并没有证明任何有用的东西,我猜编译器优化了这样的调用。

Micro-Benchmarks after warming up.

热身后的微基准。

scala>def time(a: => Unit): Long = { val t = System.currentTimeMillis; a; System.currentTimeMillis - t}
scala>def average(a: () => Long) = (for(i<-1 to 100) yield a()).sum/100

scala>average (() => time { (List[Int]() /: (1 to 1000)) { case (l, e) => l ++ List(e) } })
res1: Long = 46
scala>average (() => time { (List[Int]() /: (1 to 1000)) { case (l, e) => l ::: List(e ) } })
res2: Long = 46

As Daniel C. Sobrai said, you can append the content of any collection to a list using ++, whereas with :::you can only concatenate lists.

正如 Daniel C. Sobrai 所说,您可以使用 将任何集合的内容附加到列表中++,而 with:::您只能连接列表。