这可能会变得愚蠢,但我对以不可变方式进行 Scala Stream 评估有疑问。
假设我有一个像这样的流(所有行都在 repl 中执行);
val a = Stream(1,2,3,4,5,6,7,8,9,10);
a: scala.collection.immutable.Stream[Int] = Stream(1, ?)
当我运行以下几行时;
a(3);
a
我明白了;
scala.collection.immutable.Stream[Int] = Stream(1, 2, 3, 4, ?)
我的第一个问题是如何改变这个不可变的结构?我的意思是如果这样做(假设变量“a”定义为“var”); a = a(3) 我可能期望这样的结果。
我的另一个问题是当我运行以下几行时;
val a = Stream(1,2,3,4,5,6,7,8,9,10);
a: scala.collection.immutable.Stream[Int] = Stream(1, ?)
val b = a;
b: scala.collection.immutable.Stream[Int] = Stream(1, ?)
b(5);
scala.collection.immutable.Stream[Int] = Stream(1, 2, 3, 4, 5, 6, ?)
a
scala.collection.immutable.Stream[Int] = Stream(1, 2, 3, 4, 5, 6, ?)
正如您在执行“a”后在最后一部分中看到的那样,它似乎又发生了变化。
如果我尝试使用 List 类型进行这种分配(据我所知 List 是 Stream 的严格版本)并进行一些转换,例如 drop、take 等)
val a = List(1,2,3,4,5)
val b = a;
b.dropRight(1)
变量'a'和'b'仍然是List(1,2,3,4,5)
那么这是怎么发生的?我错过了什么?
最佳答案
Scala Streams 提供 memoization - 它们就像惰性列表,但是一旦生成元素,它们就会被存储以供将来检索。
因此,当您通过请求索引 5 处的元素“强制”Stream b
评估其某些元素时,原始 Stream a
(与 Stream 相同) object)也是强制的。
关键点:这样做不会修改流(它保持不可变),它只是更改已评估和内存的元素。
您的 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
关于scala - Scala Streams 中如何实现不变性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43149219/