결과 콜렉션의 작성 방법을 결정하는 암시적인 인수가 있지만이 경우 빌더가 사용하도록 소스 콜렉션을 간단히 쿼리한다는 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]
이 표현되는 방식으로, 소스 컬렉션 cc
에 관계없이 Set
이 빌드됩니다. 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
커뮤니티 답장 옵션이 있지만 키 입력을 알지 못합니다. 지금 서둘러야한다. –