Почему версия map
оказывается несортированной
Метод map
(вызываемый функцией, которую мы будем вызывать func
) принимает неявный параметр CanBuildFrom
, который учитывает тип коллекции, к которой вызывается map
, в дополнение к тип, который func
возвращает, чтобы выбрать подходящий тип возврата. Это используется, чтобы заставить Map.map[Int]
или BitSet.map[String]
делать правильные вещи (возвращать списки общего назначения), в то время как Map.map[(String,Int)]
или BitSet.map[Int]
также делает правильные вещи (возвращать Map
и BitSet
) соответственно.
CanBuildFrom
выбирается во время компиляции, поэтому он должен выбираться на основе статического типа набора, для которого вы вызываете map
(тип, который компилятор знает во время компиляции) , Статический тип set
равен TreeSet
, но статический тип diffset
равен Set
. Тип dynamic обоих (во время выполнения) равен TreeSet
.
Когда вы вызываете map
на set
(TreeSet
), компилятор выбирает immutable.this.SortedSet.canBuildFrom[Int](math.this.Ordering.Int)
в качестве CanBuildFrom
.
Когда вы вызываете map
на diffset
(Set
), компилятор выбирает immutable.this.Set.canBuildFrom[Int]
в качестве CanBuildFrom
.
Почему версия for
оказывается несортированной
Петля
for (i <- genSet; x = i + 1) {
println(x)
}
десугаров в
genSet.map(((i) => {
val x = i.$plus(1);
scala.Tuple2(i, x)
})).foreach(((x$1) => x$1: @scala.unchecked match {
case scala.Tuple2((i @ _), (x @ _)) => println(x)
}))
Версия desugared включает функцию map
, которая будет использовать несортированный CanBuildFrom
, как я объяснил выше.
С другой стороны, петля
for (i <- genSet) {
val x = i + 1
println(x)
}
десугаров в
genSet.foreach(((i) => {
val x = i.$plus(1);
println(x)
}))
Который вообще не использует CanBuildFrom
, поскольку новая коллекция не возвращается.