Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scala mutable val List

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?

like image 839
Sergey Nesteruk Avatar asked Feb 18 '16 19:02

Sergey Nesteruk


1 Answers

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

like image 158
Odomontois Avatar answered Sep 21 '22 03:09

Odomontois