2016-02-18 16 views
7

Pochi giorni fa ho trovato l'essenza di Paul Philip https://gist.github.com/paulp/9085746 che mostra un comportamento abbastanza strano. non ho trovato alcuna spiegazione come è possibilescala mutable val Lista

semplificato frammento di codice:

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) 

Esso funziona come previsto, senza 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) 

Che cosa sta succedendo lì?

risposta

6

Se si guarda alla List source, vedrete che contro :: classe hanno la coda definita come private[scala] var tl non val, quindi è internamente mutevole.

Questa mutazione si verifica during ListBuffer append a meno che non sia impostato il flag exported.

Questo flag è impostato in the toList method, impedendo l'ulteriore modifica degli stessi List

Ma toIterable è ereditato da SeqForwarder ->IterableForwarder, che non ha alcuna conoscenza di tale cosa, ma sta tornando stesso start oggetto as it used as underlying value

+0

Questo è un bug, giusto? Voglio dire, in nessun modo questo comportamento è in realtà inteso ... – Dima

+0

@Dima Credo che sia un bug – Odomontois

+0

Sembra che non sia proprio appunto 'append': ad esempio,' buf - = 3' muta anche il ' lst' – Dima