我正在使用 Scala 2.13.1 并在工作表中评估我的示例。
首先,我定义了两个函数,它们将a到 ( z -1) 的范围返回为流或惰性列表。
def streamRange(a: Int, z: Int): Stream[Int] = {
print(a + " ")
if (a >= z) Stream.empty else a #:: streamRange(a + 1, z)
}
def lazyListRange(a: Int, z: Int): LazyList[Int] = {
print(a + " ")
if (a >= z) LazyList.empty else a #:: lazyListRange(a + 1, z)
}
然后我调用这两个函数,获取 3 个元素的 Stream/LazyList 并将它们转换为 List:
streamRange(1, 10).take(3).toList // prints 1 2 3
lazyListRange(1, 10).take(3).toList // prints 1 2 3 4
在这里我再次做同样的事情:
val stream1 = streamRange(1, 10) // prints 1
val stream2 = stream1.take(3)
stream2.toList // prints 2 3
val lazyList1 = lazyListRange(1,10) // prints 1
val lazyList2 = lazyList1.take(3)
lazyList2.toList // prints 2 3 4
打印 1 是因为访问了函数并且打印语句在开头。没有惊喜。
但我不明白为什么额外的 4 是为惰性列表而不是流打印的。
我的假设是,在将 3 与下一个函数调用连接时,LazyList 版本会访问该函数,而在 Stream 版本中,该函数不会被访问。否则 4 将不会被打印。
这似乎是无意的行为,至少是出乎意料的。但是这种副作用的差异是否会被认为是一个错误,或者只是 Stream 和 LazyList 评估中的一个详细差异。