2016-02-18 12 views
7

Kilka dni temu znalazłem istotę Paul Philipa w gruncie https://gist.github.com/paulp/9085746, która pokazuje dość dziwne zachowanie. Nie mogę znaleźć żadnego wyjaśnienia, jak to możliwescala mutable val Lista

uproszczone fragment kodu:

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) 

To działa zgodnie z oczekiwaniami bez 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) 

Co się tam dzieje?

Odpowiedz

6

Jeśli będziesz patrzeć na List source, zobaczysz, że minusy :: klasie mają ogonem zdefiniowany jako private[scala] var tl nie val, więc jest wewnętrznie zmienny.

Ta mutacja występuje during ListBuffer append, chyba że ustawiono flagę exported.

Ta flaga jest ustawiona w the toList method, uniemożliwiając dalszą modyfikację tego samego List

Ale toIterable jest dziedziczona z SeqForwarder ->IterableForwarder, który nie ma wiedzy na temat takich rzeczy, ale wraca sam start obiekt as it used as underlying value

+0

To jest błąd, prawda? Chodzi mi o to, nie sposób to zachowanie jest faktycznie przeznaczone ... – Dima

+0

@ Dima Wierzę, że jest błąd – Odomontois

+0

Wygląda na to, że tak naprawdę nie jest po prostu 'append': na przykład,' buf - = 3' również mutuje ' lst' – Dima