2016-06-05 5 views
5

지도를 통한 이해를 위해 입력 뒤에서 혼란스러워합니다. 나의 이해는 외부 수집 유형은 일반적으로 보존되어있을 가능성이며, 우리는 다음과 같은 두 가지 경우에 예상 된 동작을 볼 :스칼라 - Map에서 Iterable으로의 예상치 못한 타입 전환을 위해?

scala> for { 
    | (k,v) <- Map(0->1,2->3) 
    | } yield k -> v 
res0: scala.collection.immutable.Map[Int,Int] = Map(0 -> 1, 2 -> 3) 

scala> for { 
    | (k,v) <- Map(0->1,2->3) 
    | foo = 1 
    | } yield k -> v 
res1: scala.collection.immutable.Map[Int,Int] = Map(0 -> 1, 2 -> 3) 

을하지만 이해를 위해 내부에 두 번째 할당을 추가 할 때 나는 놀라운 무언가를 얻을 :

scala> for { 
    | (k,v) <- Map(0->1,2->3) 
    | foo = 1 
    | bar = 2 
    | } yield k -> v 
res2: scala.collection.immutable.Iterable[(Int, Int)] = List((0,1), (2,3)) 

왜 이런 일이 발생합니까?

답변

5

scala -Xprint:typer -e "for { ... } yield k->v"을 실행하면 코드의 무심코 버전을 얻을 수 있습니다.

val m: Map[Int,Int] = Map(0->1, 2->3) 
m.map { 
    case x @ (k,v) => 
    val foo = 1 
    val bar = 2 
    (x, foo, bar) 
}.map { 
    case ((k,v), foo, bar) => (k, v) 
} 

그래서 당신이 알 수 있습니다 무엇에 대한-이해가 .map 호출로 변환됩니다 때, 실제로 k->v을 함께 foobar을 반환하는 점이다 : 여기에 당신이 무엇을 얻을의매우 단순화 된 버전입니다 이는 Tuple3[(Int,Int), Int, Int]임을 의미합니다. Tuple3 객체의 반복 가능 항목은 Map으로 바꿀 수 없으므로 Iterable을 반환해야한다고 가정합니다. 그러나 Tuple2 개체의 모음 인 올바른 출력을 얻으려면 보조 .map을 수행하여 foobarTuple3에서 삭제하지만이 시점에서 더 이상은 Map이어야한다는 것을 알지 못합니다. 정보가 이월되지 않도록 .map으로 전화합니다.

중간 표현이 Tuple2[(Int,Int), Int]이기 때문에 하나의 과제 만 사용한 귀하의 예는 운이 좋을 것입니다. 당신이 직접 .map를 사용하는 경우

한편

, 그것은 작동합니다

Map(0->1, 2->3).map { 
    case (k,v) => 
    val foo = 1 
    val bar = 2 
    k -> v 
}