【问题标题】:LazyList in ScalaScala 中的惰性列表
【发布时间】:2020-12-28 22:49:05
【问题描述】:

假设我们有以下 LazyList 定义:

val fibs: LazyList[BigInt] = BigInt(0) #:: BigInt(1) #::
fibs.zip(fibs.tail).map(pair => pair._1 + pair._2)

我的问题是它是如何执行的,因为这个定义说我们取尾部并为每一对(来自 zip)进行计算。但是,如果我们想计算索引为 10 的元素,我们已经有了 ...8、9 的值。所以问题是......这是以某种方式优化的,还是对于每个下一个元素,我们都会遍历所有对?

【问题讨论】:

  • 您可以在map 中添加println 进行检查。 LazyLists 被记忆,它们记住已经计算过的元素。
  • ScalaDocs page 使用相同的fibs() 算法非常详细地说明了记忆化、抓住头部、无限回归、不变性等概念,以及它们如何应用于@ 987654326@。答案是肯定的,只要有东西占据列表的头部,就会发生记忆。
  • @jwvh 好的,这将是一个答案!

标签: scala


【解决方案1】:

添加上-

  1. LazyList 本质上是一个 LinkedList,这意味着要访问第 10 个元素,您必须先遍历所有元素。

  2. #:: 操作符/方法本质上最终创建了一个新类,这是库代码-

    implicit def toDeferrer[A](l: => LazyList[A]): Deferrer[A] = new Deferrer[A](() => l)
    
    final class Deferrer[A] private[LazyList] (private val l: () => LazyList[A]) extends AnyVal {
    
      /** Construct a LazyList consisting of a given first element followed by elements
        *  from another LazyList.
        */
      def #::[B >: A](elem: => B): LazyList[B] = newLL(sCons(elem, l()))
    
      /** Construct a LazyList consisting of the concatenation of the given LazyList and
        *  another LazyList.
        */
      def #:::[B >: A](prefix: LazyList[B]): LazyList[B] = prefix lazyAppendedAll l()
    }
    

然后对象创建的顺序是-

  1. 懒洋洋地包裹在 Function0 fibs.zip(fibs.tail).map(pair => pair._1 + pair._2)
  2. 之后我们有 cons 运算符#:: 可用,我们附加一个新的头部BigInt(1)
  3. 最后,我们再次将一个新头附加到 LinkedList BigInt(0),现在我们的递归结构已准备就绪。
  4. 再一次,一切仍然是惰性构建的,这就是为什么我们最终不会取消对 null 的引用

当我们调用 head 时,我们开始展开,然后懒惰开始采取行动。

此外,LazyList 内部使用此 State 结构来建模头部和尾部

private sealed trait State[+A] extends Serializable {
  def head: A
  def tail: LazyList[A]
}

这个结构是它在第一次访问每个元素时记忆的内容。

private lazy val state: State[A] = { ... }

【讨论】:

  • 但问题是每次我们访问下一个元素时列表是否完全“重新创建”?
  • 酷,接受的答案!我真的很想了解更多关于记忆的信息。例如,我已经看到可以创建自己的 memoize 函数以使您的递归函数更快。这对我来说是一个新概念,我对语法也不太熟悉。
  • 看看这是否有帮助,你可以传递这个任何函数,它会返回它的记忆变体github.com/gagandeepkalra/category-theory/blob/master/src/main/…
猜你喜欢
  • 2021-05-12
  • 2018-05-07
  • 1970-01-01
  • 1970-01-01
  • 2012-02-10
  • 1970-01-01
  • 2012-09-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多