var set = TreeSet(5,4,3,2,1)
println(set)
val diffSet: TreeSet[Int] = set
// if I change above code to val diffSet: Set[Int] = set
// the result is
Set does not guarantee ordering. Even if the underlying class is a TreeSet, if the expected result is a Set you'll loose the ordering in the first transformation you do.
If you want ordering, do not use Set. I suggest, say, SortedSet.
You can do:
scala> for (i <-genSet.view; x = i + 1) println(x)
2
3
4
5
6
Although, it's the type of trick that when you look at it after a few months, you may wonder why you added .view ...
map version winds up unsortedThe map method (called with a function that we'll call func) takes an implicit CanBuildFrom parameter that takes into account the type of the collection that map is being called on, in addition to the type that func returns to choose an appropriate return type. This is used to make Map.map[Int] or BitSet.map[String] do the right thing (return general purpose lists) while Map.map[(String,Int)] or BitSet.map[Int] also do the right thing (return a Map and a BitSet) respectively.
The CanBuildFrom is chosen at compile time, so it must be chosen based on the static type of the set that you call map on (the type the compiler knows about at compile time). The static type of set is TreeSet, but the static type of diffset is Set. The dynamic type of both (at runtime) is TreeSet.
When you call map on set (a TreeSet), the compiler chooses immutable.this.SortedSet.canBuildFrom[Int](math.this.Ordering.Int) as the CanBuildFrom.
When you call map on diffset (a Set), the compiler chooses immutable.this.Set.canBuildFrom[Int] as the CanBuildFrom.
for version winds up unsortedThe loop
for (i <- genSet; x = i + 1) {
println(x)
}
desugars into
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)
}))
The desugared version includes a map function which will use the unsorted CanBuildFrom as I explained above.
On the other hand, the loop
for (i <- genSet) {
val x = i + 1
println(x)
}
desugars into
genSet.foreach(((i) => {
val x = i.$plus(1);
println(x)
}))
Which doesn't use a CanBuildFrom at all, since no new collection is being returned.
Change the sig of genSet to return a SortedSet
def genSet:SortedSet[Int] = {
TreeSet(5, 4, 3, 2, 1)
}
This is probably some sort of bug. I would have expected your code to work too.
I think map is the culprit. This results in the same behavior:
for (i <- genSet.map(_ + 1)) { println(i) }
And for(i <- genSet; x = i + 1) equates to for(x <- genSet.map({i => i + 1}))