4

見つめている

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、 a を返すことを期待しています。結果が に明示的に型指定されている場合、VectorBuilderこれは によって返されます。CanBuildFromSeq

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です。

したがって、明示的に をビルドしたかったのですが、 Scala コレクションのメモリ フットプリントの特性によるとSeq、結果はより多くの RAM を必要とする になります。List

では、なぜ最後に a をSeq.newBuilder返す aListBufferを返すのListでしょうか?

4

4 に答える 4

1

わかりましたが、あなたはそれを信じるつもりはありません。反例をオン-Yinfer-debugにすると、CanBuildFrom

[search] $line14.$read.$iw.$iw.build[scala.this.Int, Seq[scala.this.Int]](1, 2) with pt=generic.this.CanBuildFrom[scala.this.Nothing,scala.this.Int,Seq[scala.this.Int]] in module class $iw, eligible:
  fallbackStringCanBuildFrom: [T]=> generic.this.CanBuildFrom[String,T,immutable.this.IndexedSeq[T]]
[solve types] solving for T in ?T
inferExprInstance {
  tree      scala.this.Predef.fallbackStringCanBuildFrom[T]
  tree.tpe  generic.this.CanBuildFrom[String,T,immutable.this.IndexedSeq[T]]
  tparams   type T
  pt        generic.this.CanBuildFrom[scala.this.Nothing,scala.this.Int,Seq[scala.this.Int]]
  targs     scala.this.Int
  tvars     =?scala.this.Int
}
[search] considering no tparams (pt contains no tvars) trying generic.this.CanBuildFrom[String,scala.this.Int,immutable.this.IndexedSeq[scala.this.Int]] against pt=generic.this.CanBuildFrom[scala.this.Nothing,scala.this.Int,Seq[scala.this.Int]]
[success] found SearchResult(scala.this.Predef.fallbackStringCanBuildFrom[scala.this.Int], ) for pt generic.this.CanBuildFrom[scala.this.Nothing,scala.this.Int,Seq[scala.this.Int]]
[infer implicit] inferred SearchResult(scala.this.Predef.fallbackStringCanBuildFrom[scala.this.Int], )

本当に、

  implicit def fallbackStringCanBuildFrom[T]: CanBuildFrom[String, T, immutable.IndexedSeq[T]] =
    new CanBuildFrom[String, T, immutable.IndexedSeq[T]] {
      def apply(from: String) = immutable.IndexedSeq.newBuilder[T]
      def apply() = immutable.IndexedSeq.newBuilder[T]
    }

Iterable が文字列ではないというのはどういうことですか?

trait CanBuildFrom[-From, -Elem, +To]

これは、Nothing または Any のいずれかを推論することの弊害です。

編集: 申し訳ありませんが、言い間違えました。明示的に何も言わなかったようです。

アップデート:

CBF は で反変であるためFrom、 からの CBF は からStringの CBF として機能しますNothing

scala> typeOf[CanBuildFrom[Nothing,Int,Seq[Int]]] <:< typeOf[CanBuildFrom[String,Int,Seq[Int]]]
res0: Boolean = false

scala> typeOf[CanBuildFrom[String,Int,Seq[Int]]] <:< typeOf[CanBuildFrom[Nothing,Int,Seq[Int]]]
res1: Boolean = true

たとえば、 からビルドする必要がある場合はimmutable.Map、CBF をcollection.Map機能させる必要があります。

他の誰かがコメントしたように、それはNothing. しかし、あなたはあなたが求めたものを手に入れます。つまり、指定不足です。これは、返されるもの、ベクトルなど、あまり気にしないことを意味します。

于 2013-07-20T00:14:54.807 に答える