2017-03-31 52 views
2

它可能會變得很愚蠢,但我對以不可變方式評估Scala流評估有疑問。假設我有一個像這樣的Stream(所有行在repl中執行);Scala流如何實現不變性?

val a = Stream(1,2,3,4,5,6,7,8,9,10); 

一個:scala.collection.immutable.Stream [INT] =流(θ1,)

當運行下面的行;

a(3); 
a 

我得到了;

scala.collection.immutable.Stream [INT] =流(1,2,3,4,?)

第一個問題是如何這個不可變結構得到改變?我的意思是如果這樣做(假設變量'a'定義爲'var'); a = a(3)我可能會期待這樣的結果。

我的另一個問題是,當我跑下面的線;

val a = Stream(1,2,3,4,5,6,7,8,9,10); 

一個:scala.collection.immutable.Stream [INT] =流(1,θ)

val b = a; 

B:scala.collection.immutable.Stream [INT] =流(1,θ)

b(5); 

scala.collection.immutable.Stream [INT] =流(1,2,3,4,5,6,?)

a 

scala.collection.immutable.Stream [INT] =流(1,2,3,4,5,6,?)

正如你可以在最後部分看到執行'a'後,它似乎又改變了。

如果我嘗試這種與列表類型分配(據我所知名單是流的嚴格的版本)和不喜歡滴一些改造,採取等)

val a = List(1,2,3,4,5) 
val b = a; 
b.dropRight(1) 

變量「a」和'b'仍然是列表(1,2,3,4,5)

那麼這是怎麼發生的以及我錯過了什麼?

回答

2

斯卡拉流提供memoization - 他們就像懶惰的列表,但一旦生成元素,他們被存儲爲將來檢索。

因此,當您通過請求索引5處的元素來「強制」流b來評估它的某些元素時,原始流a(這是相同的Stream對象)也被強制。

要點:這樣做不會修改流(它仍然是不可變的),它只是改變哪些元素已被評估和memoized。

Stream(1,?)Stream(1,2,3,4,5,6,?)是相同的流,只計算爲一個不同程度的:

scala> val a = Stream(1,2,3,4,5,6,7,8,9,10); 
a: scala.collection.immutable.Stream[Int] = Stream(1, ?) 

scala> val b = a 

scala> a(3) 
res9: Int = 4 

scala> a 
res10: scala.collection.immutable.Stream[Int] = Stream(1, 2, 3, 4, ?) 

scala> b 
res11: scala.collection.immutable.Stream[Int] = Stream(1, 2, 3, 4, ?) 

scala> Stream(1,2,3,4,5,6,7,8,9,10) == a 
res12: Boolean = true 

scala> Stream(1,2,3,4,5,6,7,8,9,10) == b 
res13: Boolean = true