scala - Scala Streams 中如何实现不变性?

标签 scala stream immutability memoization

这可能会变得愚蠢,但我对以不可变方式进行 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/

相关文章:

scala - 列出S3上的文件

java - java如何在内部将任何类型的文件(图像、pdf等)转换为字节数组?

c++ - 为字符缓冲区实现 istream get?

java - 不变性是否保证线程安全?

python - 允许在 Python 中子类化的不可变类型

scala - 如何在 Scala 中的函数式编程中处理递归函数中的选项?

java - 无法通过伴随对象调用函数

java - 无法直接从 Spark RDD 向 Ignite 写入/保存数据

python - 在 Python 中创建流类

javascript - 不变性助手中的拼接