【发布时间】:2013-07-21 03:01:46
【问题描述】:
看着
val sb = Seq.newBuilder[Int]
println(sb.getClass.getName)
sb += 1
sb += 2
val s = sb.result()
println(s.getClass.getName)
输出是
scala.collection.mutable.ListBuffer
scala.collection.immutable.$colon$colon
使用 Scala 2.10.1。
例如,我希望Seq.newBuilder 返回VectorBuilder。如果结果显式输入到Seq,则由CanBuildFrom 返回:
def build[T, C <: Iterable[T]](x: T, y: T)
(implicit cbf: CanBuildFrom[Nothing, T, C]): C = {
val b = cbf()
println(b.getClass.getName)
b += x
b += y
b.result()
}
val s: Seq[Int] = build(1, 2)
println(s.getClass.getName) // scala.collection.immutable.Vector
在这种情况下,构建器是VectorBuilder,结果的类是Vector。
所以我明确地想要构建一个Seq,但根据Scala collection memory footprint characteristics,结果是一个需要更多内存的List。
那么为什么Seq.newBuilder 会返回一个ListBuffer,它最终会给出一个List?
【问题讨论】:
-
有点像你的stackoverflow.com/q/17599652/1296806 的骗子,但我真的不明白你对CanBuildFrom 的评论是什么意思。这很有趣。顺便说一句,我认为如果一个问题得到相同的答案,它可能是一个骗局。不要忘记阅读概述文档和 Spiewak stackoverflow.com/a/6934116/1296806
-
@som-snytt 如果
List是Seq的默认实现,那么我希望CanBuildFrom也会返回List,如果结果输入为@987654341 @(为了一致性)。我现在可以添加此评论,因为其中一个答案表明List是Seq的默认值。至于 Spiewak 的回答,我以前读过,但这又提出了另一个问题:Seq和List都是特征,而Vector不是。但我想要的只是一个Seq(Iterable有顺序),例如作为方法的结果。最有效的实现。应用于履行合同。 -
“最有效”的概念是上下文相关的,因此人们争论不休。我认为从历史上看,Lisp 类型是根据 List 来思考的。但是,对于 CanBuildFrom,您从什么开始构建显然很重要,因此 CanBuild From,因此您并没有摆脱困境。但我明白你的意思:你想要求一个默认的 CBF。好吧,你得到的默认值恰好是为一个常见的用例 String 制造的,你显然想要一个索引 Seq。
-
我不敢相信 SO 对 cmets 应用 Twitterish 长度限制。无论如何:为什么?我不知道。您可能会争辩说应该从左到右处理字符串;除了人们假设字符串是由类似数组的东西支持的。我们一直在做 s.indexOf(c)。
-
@som-snytt 上下文是
Seq特征。所以我想为此获得“最有效”的实现。