我使用Stream来创建一个延迟序列。我的序列是用++和其他序列组合起来的。但是我的代码不工作。为什么?
def select[T1, T2](s: Stream[T1], map: T1=>T2): Stream[T2] = {
for (sv <- s) yield map(sv)
}
var innerCounter = 0
var proxy = (x: Int) => { innerCounter += 1; x }
var list: Stream[Int] = select[Int,Int](Stream.empty, k => k)
for (nc <- 0 until 10) {
list = select[Int,Int](Stream.empty, k => k)
var i: Int = 0
while (i < CountConcat) {
i += 1
list = list ++ select[Int,Int](Stream(0), k => proxy(i + 100))
}
}
assert(innerCounter == 0)
你的失败可以简化得多:
var innerCounter = 0
val proxy = (x: Int) => { innerCounter += 1; x }
Stream(0).map(k => proxy(100))
assert(innerCounter == 0)
我考虑到你的select函数只不过是map。
流的map/flatMap将严格计算流的头部,而不是流的尾部,如果尾部是惰性的。因此,在这里,我们是在单个元素流上进行映射,并且代理函数只计算一次。
所以,因为你是在单个元素流上进行映射的,在你将它们附加到你正在累积的流上之前,你会看到你的代理函数每次都被调用。
试试这个:
var innerCounter = 0
val proxy = (x: Int) => { innerCounter += 1; x }
(Stream.empty ++ Stream(0) ++ Stream(1)).map(k => proxy(100))
assert(innerCounter == 1)
,你会发现断言成立。流的头部是严格映射的,但流的尾部没有求值。