【问题标题】:Why does iterating over multiple streams only iterate over the first element?为什么迭代多个流只迭代第一个元素?
【发布时间】:2017-12-15 04:13:14
【问题描述】:

我最近在我的代码中遇到了一个错误,其中迭代多个流会导致它们仅迭代第一项。我将我的流转换为缓冲区(我什至不知道我正在调用的函数的实现返回一个流)并且问题得到了解决。我觉得这很难相信,所以我创建了一个最低限度的可验证示例:

def f(as: Seq[String], bs: Seq[String]): Unit =
    for {
      a <- as
      b <- bs
    } yield println((a, b))

  val seq = Seq(1, 2, 3).map(_.toString)
  f(seq, seq)

  println()

  val stream = Stream.iterate(1)(_ + 1).map(_.toString).take(3)
  f(stream, stream)

打印其输入的每个组合的函数,并使用 Seq [1, 2, 3] 和 Stream [1, 2, 3] 调用。

带有seq的结果是:

(1,1)
(1,2)
(1,3)
(2,1)
(2,2)
(2,3)
(3,1)
(3,2)
(3,3)

流的结果是:

(1,1)

我只能在迭代多个生成器时复制它,迭代单个流似乎工作正常。

所以我的问题是:为什么会发生这种情况,我该如何避免这种故障?也就是说,在每次多生成器迭代之前都没有使用.toBuffer.to[Vector]

谢谢。

【问题讨论】:

    标签: scala stream


    【解决方案1】:

    您使用 for-comprehension 的方式(在产量中带有 println)有点奇怪,可能不是您想要做的。如果您真的只想打印出条目,那么只需使用foreach。这将强制像Stream 这样的惰性序列,即

    def f_strict(as: Seq[String], bs: Seq[String]): Unit = {
      for {
        a <- as
        b <- bs
      } println((a, b))
    }
    

    f 出现奇怪行为的原因是 Streams 是惰性的,并且仅根据需要计算(然后记忆)元素。由于您从不使用由f 创建的Stream(必然是因为您的f 返回Unit),所以只有头部被计算(这就是为什么您看到单个(1, 1)。)如果您而是让它返回它生成的序列(类型为Seq[Unit]),即

    def f_new(as: Seq[String], bs: Seq[String]): Seq[Unit] = {
      for {
        a <- as
        b <- bs
      } yield println((a, b))
    }
    

    然后你会得到以下行为,希望有助于阐明发生了什么:

    val xs = Stream(1, 2, 3)
    val result = f_new(xs.map(_.toString), xs.map(_.toString))
    //prints out (1, 1) as a result of evaluating the head of the resulting Stream
    result.foreach(aUnit => {})
    //prints out the other elements as the rest of the entries of Stream are computed, i.e.
    //(1,2)
    //(1,3)
    //(2,1)
    //...
    result.foreach(aUnit => {})
    //probably won't print out anything because elements of Stream have been computed, 
    //memoized and probably don't need to be computed again at this point.
    

    【讨论】:

    • 省略 yield 正是我在 f_strict 中所做的。
    • 我怎么错过了
    猜你喜欢
    • 2015-07-26
    • 1970-01-01
    • 2023-03-27
    • 2015-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-19
    • 1970-01-01
    相关资源
    最近更新 更多