【问题标题】:Understanding scanRight in Scala理解 Scala 中的 scanRight
【发布时间】:2019-06-02 21:48:47
【问题描述】:

我无法理解 Scala 中 scanRight 函数的以下实现。

def scanRight[B](z: B)(f: (A, => B) => B): Stream[B] =
    foldRight((z, Stream(z)))((a, p0) => {
      lazy val p1 = p0
      val b2 = f(a, p1._1)
      (b2, cons(b2, p1._2))
    })._2

scanRight 的一个典型应用是 Stream(1, 2, 3).scanRight(0)(_ + _).toList

产生熟悉的List(1+2+3, 1+2, 1, 0)

特别是,我不明白p0在这里是什么。它似乎是一个元组?但是这个元组是从哪里来的呢?

请注意,此具体实现取自here

谢谢,如果您需要更多信息,请告诉我。

【问题讨论】:

    标签: scala collections


    【解决方案1】:

    问题已得到解答,但注意到您发布的结果不是预期的结果(这将是 foldLeft 操作的相反结果。)

    鉴于此函数使用foldRight,扫描的值将从右到左给出,结果如下: List(1+2+3, 2+3, 3, 0)

    最后的0是初始值(0,Stream(0))

    我希望我解释得很好。

    【讨论】:

      【解决方案2】:

      元组是foldRight 调用的参数:(z, Stream(z))。元组中的第一个值是到目前为止的扫描结果。第二个值是Stream,它将是scanRight 调用的最终结果。

      fold 的每次传递都通过对序列中的当前值 (a) 和前一个扫描值(元组中的第一个元素)调用 f 来更新扫描结果。使用cons 将结果添加到流(在元组的第二个元素中)。这两个值都作为新元组传递给 fold 的下一次迭代。

      fold 完成时,它返回元组,但scanRight 只需要第二个元素,因此从该元组 (._2) 中提取并返回。

      【讨论】:

      • 嗨蒂姆,感谢您的帮助。 (z, Stream(z))foldRight 调用的零元素,对吗?所以,我虽然这最终会在foldRight 中应用。为什么说它持有“元组的第一个值”?
      • 此外,我还认为foldRight 应用了{} 之间指定的函数,参数是流的头部和缺点。但这里似乎并非如此。你知道我在这里想念什么吗?
      • 元组是foldRight开始 元素,并且是第一次调用块时p0 的值。但是因为foldRight 向后扫描列表(从头到尾),所以它也是结果中的 last 元素。使用元组调用块,其中第一个值是列表中的当前元素,第二个值是最后一次调用块返回的值。
      猜你喜欢
      • 2017-03-28
      • 1970-01-01
      • 2016-10-20
      • 2017-03-26
      • 2014-04-10
      • 2015-10-21
      • 2018-05-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多