2016-02-18 23 views
7

Vor wenigen Tagen fand ich Paul Philip's Kern https://gist.github.com/paulp/9085746, der ziemlich merkwürdiges Verhalten zeigt. Ich habe keine Erklärung finden, wie ist das möglichscala veränderbares val Liste

vereinfacht Code-Schnipsel:

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) 

Es funktioniert wie erwartet ohne 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) 

Was ist da los?

Antwort

6

Wenn man sich die List source aussehen werde, werden Sie sehen, dass die Nachteile :: Klasse haben den Schwanz definiert als private[scala] var tl nicht val, so ist es intern wandelbar.

Diese Mutation tritt auf during ListBuffer append, wenn exported Flag gesetzt ist.

Dieses Flag wird in the toList method gesetzt, verhindert weitere Modifikation der gleichen List

Aber toIterable von SeqForwarder vererbt wird ->IterableForwarder, die kein Wissen über so etwas, aber kehrt gleiches start Objekt as it used as underlying value

+0

Das ist ein Fehler, oder? Ich meine, auf keinen Fall ist dieses Verhalten eigentlich beabsichtigt ... – Dima

+0

@Dima Ich glaube, es ist ein Fehler – Odomontois

+0

Es scheint, als wäre es nicht wirklich nur 'append': zum Beispiel,' buf - = 3' mutiert auch die ' lst – Dima