集合框架的大部分实现复杂性源于这样一个事实,即 Scala 可以 - 与 C# 的 LINQ 或其他集合框架不同 - 为高阶函数返回“最佳”集合类型:
val numbers = List(1,2,3,4,5)
numbers map (2*) // returns a List[Int] = List(2, 4, 6, 8)
val doubles = Array(1.0, 2.0, 3.0)
doubles filter (_ < 3) // returns Array[Double] = Array(1.0, 2.0)
为什么这个原则不适用于 seq
、par
、view
、force
等方法?
numbers.view.map(2*).force
// returns Seq[Int] = List(2, 4, 6, 8)
numbers.seq
// returns scala.collection.immutable.Seq[Int] = List(1, 2, 3, 4)
doubles.par.seq
// returns scala.collection.mutable.ArraySeq[Double] = ArraySeq(1.0, 2.0, 3.0)
是否存在阻止其工作的技术限制?
或者这是设计/意图?
考虑到 LINQ 基本上是惰性的,Scala 的等价物(view
、force
)并不是更安全(仅当使用严格方法时),对吗?
最佳答案
可以将更多类型信息嵌入到并行集合类中,这样您就可以取回开始时使用的集合,这是事实。这意味着在通过调用 par
将 List
转换为 ParVector
之后(在 O(n) 中,因为元素被复制到向量中)然后调用 seq
,你会再次得到一个 List
。要使用 seq
获取列表,您必须将向量中的所有元素复制回列表中。相反发生的是:
ParVector
在seq
被调用时被转换回Vector
- 它在 O(1) 中被转换- 在此向量上再次调用
par
将在 O(1) 中为您提供ParVector
,因为它们向量和并行向量共享相同的基础数据
请注意,将列表等集合转换为并行集合时必须对其进行重构,否则无法有效地并行化其上的操作。
因此,您不必在调用 par
和 seq
时重复为复制付费 - 转换变得更加高效。由于并行集合的主要目标是提高效率,因此这被认为比统一返回类型原则更重要。
关于c# - Scala collection 的seq/par/view/force 是否可以被视为违反统一返回类型原则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6390028/