If I call toSeq
on an immutable Set
collection I get an ArrayBuffer
.
scala> Set(1,2,3).toSeq // returns Seq[Int] = ArrayBuffer(1, 2, 3)
This surprises me. Given Scala's emphasis on using immutable data structures, I expect to get back an immutable sequence like a Vector
or List
instead of a mutable ArrayBuffer
. The returned ordering of the set elements should of course be undefined, but there doesn't seem to be any semantic reason why that ordering should also be mutable.
In general, I expect Scala operations to always produce immutable results unless I explicitly request a mutable one. This has been my assumption all along, but it is an incorrect one here, and I actually just spent an hour debugging a problem where the unexpected presence of an ArrayBuffer
led to a runtime error in a match
statement. My fix was to change Set(...).toSeq
to Set(...).toList
, but this feels like a hack because there's nothing about my application that requires a list in particular at that point.
Is having Set(...).toSeq
return a mutable object a flaw in Scala's implementation, or is there a principle I am misunderstanding here?
This is Scala 2.9.2.
Here is the recent thread on whether Seq should mean immutable.Seq.
Roland Kuhn:
collection.Seq not having mutators is not at all a valid defense!
The example of mutable varargs is rather sneaky.
Recently,
scala> Set(1,2,3)
res0: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
scala> res0.toSeq
res1: Seq[Int] = ArrayBuffer(1, 2, 3)
scala> res0.to[collection.immutable.Seq]
res2: scala.collection.immutable.Seq[Int] = Vector(1, 2, 3)