結果コレクションの作成方法を決定する暗黙の引数が存在しますが、ソースコレクションにはビルダーが使用するかどうかが単に問い合わせされるというKolmarのコメントを抽出します。
Iterable.map
:
def map[B, That](f: (A) ⇒ B)(implicit bf: CanBuildFrom[Iterable[A], B, That]): That
暗黙的範囲はIterable
とInt
含む型引数に関連するタイプを含みます。
Iterable
は、ソースコレクションでgenericBuilder
を呼び出す「汎用」CanBuildFrom
を定義します。これは、結果の型がソースに結びついている方法です。
逆に、結果のコレクションはCanBuildFrom[From = Nothing, _, _]
を取ることによってソースから離婚しています。これはcc.to[Set]
がどのように表現されているかで、Set
はソースコレクションcc
に関係なく構築されています。 map
のような演算の場合、方法collection.breakOut
は、このようなCanBuildFrom
を提供し、その結果のタイプが有益に推定され得る。
希望する動作の任意CanBuildFrom
を注入することができる:
$ scala
Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_92).
Type in expressions for evaluation. Or try :help.
scala> val m = Map("a" -> 1, "b" -> 1)
m: scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 1)
scala> val k = m.keys
k: Iterable[String] = Set(a, b)
scala> import collection.{generic, mutable}, generic.{CanBuildFrom => CBF}, mutable.ListBuffer
import collection.{generic, mutable}
import generic.{CanBuildFrom=>CBF}
import mutable.ListBuffer
scala> implicit def `as list`: CBF[Iterable[_], Int, List[Int]] =
| new CBF[Iterable[_], Int, List[Int]] {
| def apply() = new ListBuffer[Int]
| def apply(from: Iterable[_]) = apply()
| }
as$u0020list: scala.collection.generic.CanBuildFrom[Iterable[_],Int,List[Int]]
scala> k.map(m)
res0: List[Int] = List(1, 1)
その完了タイプを示すことができる追加ワース2.11.8のとおり
scala> k.map(m) //print<tab>
$line4.$read.$iw.$iw.k.map[Int, Iterable[Int]]($line3.$read.$iw.$iw.m)(scala.collection.Iterable.canBuildFrom[Int]) // : Iterable[Int]
はbreakOut
使用:
scala> k.map(m)(collection.breakOut)
res1: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 1)
scala> k.map(m)(collection.breakOut) //print
$line4.$read.$iw.$iw.k.map[Int, scala.collection.immutable.IndexedSeq[Int]]($line3.$read.$iw.$iw.m)(scala.collection.`package`.breakOut[Any, Int, scala.collection.immutable.IndexedSeq[Int]](scala.Predef.fallbackStringCanBuildFrom[Int])) // : scala.collection.immutable.IndexedSeq[Int]
示されているように、実際にはCanBuildFrom
intをピックアップします。比較
scala> "abc".map(_ + 1)
res2: scala.collection.immutable.IndexedSeq[Int] = Vector(98, 99, 100)
scala> "abc".map(_ + 1) //print
scala.Predef.augmentString("abc").map[Int, scala.collection.immutable.IndexedSeq[Int]](((x$1: Char) => x$1.+(1)))(scala.Predef.fallbackStringCanBuildFrom[Int]) // : scala.collection.immutable.IndexedSeq[Int]
:次のような操作に終了
scala> k.map(m)(collection.breakOut) : List[Int] //print
(($line6.$read.$iw.$iw.k.map[Int, List[Int]]($line5.$read.$iw.$iw.m)(scala.collection.`package`.breakOut[Iterable[String], Int, List[Int]](scala.collection.immutable.List.canBuildFrom[Int]))): scala.`package`.List[scala.Int]) // : List[Int]
canonical Q&A on breakOut。
また、型をソースに結び付けることをオーバーライドする共通のメカニズムは 'scala.collection.breakOut'を使うことです。 'foo.keys.map(foo)(collection.breakOut)'は 'Vector(1、1):scala.collection.immutable.IndexedSeq [Int]'になります。これはまた、結果から型推論を可能にします。したがって、 'val :: List [Int] = foo.keys.map(foo)(collection.breakOut)'はランタイム 'List(1、1)'になります。 – Kolmar
コミュニティ回答オプションもありますが、私はそのキーストロークをわかりません。現時点で急ぐ必要があります。 –