【问题标题】:Lazy stream does not work惰性流不起作用
【发布时间】:2014-09-23 09:24:53
【问题描述】:

我正在使用 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)

【问题讨论】:

  • 是的,为什么?请发布错误消息。你的代码试图实现什么?
  • 我尝试实现对文件的延迟访问。在我的场景中,代理函数将在随机位置从打开的文件中读取。但! Stream init 和打开文件的时间之间有很大的差距。并且严格评估流的头部对我来说是不可接受的

标签: scala stream lazy-evaluation lazy-sequences


【解决方案1】:

你的失败可以大大简化:

var innerCounter = 0
val proxy = (x: Int) => { innerCounter += 1; x }
Stream(0).map(k => proxy(100))
assert(innerCounter == 0)

我考虑到您的选择功能只不过是地图。

当尾部是惰性的时,Stream 的 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)

你会发现这个断言成立。我们的流的头部被严格映射,但流的尾部没有被评估。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-25
    • 1970-01-01
    • 2015-05-29
    • 1970-01-01
    • 2012-11-04
    • 2015-09-13
    • 2016-10-21
    相关资源
    最近更新 更多