Few days ago I found Paul Philip’s gist https://gist.github.com/paulp/9085746 which shows quite strange behavior. I did not find any explanation how is that possible
simplified code snippet:
val buf = new ListBuffer[Int]()
buf ++= Seq(1,2,3)
val lst: List[Int] = buf.toIterable.toList
println(lst) //List(1,2,3)
buf ++= Seq(4,5,6)
println(lst) //List(1,2,3,4,5,6)
It works as expected without toIterable
val buf = new ListBuffer[Int]()
buf ++= Seq(1,2,3)
val lst: List[Int] = buf.toList
println(lst) //List(1,2,3)
buf ++= Seq(4,5,6)
println(lst) //List(1,2,3)
What is going on there?
If you'll look at the List
source, you'll see that cons ::
class have its tail defined as private[scala] var tl
not val
, so it's internally mutable.
This mutation is occuring during ListBuffer
append unless exported
flag is set.
This flag is set in the toList
method, preventing further modification of the same List
But toIterable
is inherited from SeqForwarder
-> IterableForwarder
, which has no knowledge about such thing, but is returning same start
object as it used as underlying
value
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With