【问题标题】:Why does my takeWhile fail to work with my Stream为什么我的 takeWhile 无法与我的 Stream 一起使用
【发布时间】:2011-10-28 00:34:41
【问题描述】:

以下代码打印“*1”。令人困惑的是,如果我删除它返回“*4”的评论,这是我所期待的

var max = 0
lazy val list: Stream[Int] = 1 #:: Stream.from(2)
list.takeWhile {
  x =>
    max = x
    x < 4
}//.foreach(println)
println("*" + max)

【问题讨论】:

    标签: scala


    【解决方案1】:

    首先:第二行中的lazy 没有做任何事情——您可以删除它并获得相同的结果。

    更重要的是:takeWhile实际上是惰性的,因为它只是返回另一个Stream,并且在需要之前不会评估该流头部之外的任何内容。考虑以下几点:

    val s = Stream.from(1).takeWhile(_ > 0)
    

    你和我都知道s 将是一个无限流,但如果我们启动 REPL 并输入它,它会非常高兴地评估它:

    scala> val s = Stream.from(1).takeWhile(_ > 0)
    s: scala.collection.immutable.Stream[Int] = Stream(1, ?)
    

    在您的示例中发生了同样的事情:您传递给 takeWhile(Int) ⇒ Boolean 不会得到流头部之外的任何元素,直到像您的 foreach 这样的东西使必要的。

    您可以通过在 takeWhile 谓词中添加类似 println 的内容来更加显着地看到这一点:

    scala> val s = Stream.from(1).takeWhile { x => println("Checking: " + x); x < 4 }
    Checking: 1
    s: scala.collection.immutable.Stream[Int] = Stream(1, ?)
    
    scala> val l = s.toList
    Checking: 2
    Checking: 3
    Checking: 4
    l: List[Int] = List(1, 2, 3)
    

    显然,谓词只会在流的头部被调用,直到我们通过调用 toList 来强制评估流的其余部分。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-27
      • 2013-12-06
      • 1970-01-01
      • 2011-12-25
      相关资源
      最近更新 更多