4

当我找到#2 问题的非常优雅的解决方案时,我一直在 Scala 中做一些欧拉问题。但是,我在理解它为什么起作用时遇到了一些问题。据我所知,它需要1并将其添加fibbonaciNumbers.scanLeft(1)(_ + _)到初始化相同的数组中。怎么可能调用scanLeft()目前为空的 LazyList?

/**
  * Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2,
  * the first 10 terms will be:
  * 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
  * By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the
  * even-valued terms.
  *
  * Result:
  */
object Problem2 {

  def main(args: Array[String]): Unit = {
    println("The result is " + fibbonaciNumbersSum(4000000))
  }

  // Why is it possible to call .scanLeft on an empty list (because it's empty in the moment we call it, right?)
  lazy val fibbonaciNumbers: LazyList[Int] = 1 #:: fibbonaciNumbers.scanLeft(1)(_ + _)

  private def fibbonaciNumbersSum(limit: Int) = fibbonaciNumbers.takeWhile(_ <= limit).filter(_ % 2 == 0).sum
}
4

1 回答 1

2

LazyList 不为空。查看 Stream 的文档:

/** Construct a stream consisting of a given first element followed by elements
 *  from a lazily evaluated Stream.
 */
def #::[B >: A](hd: B): Stream[B] = cons(hd, tl)

因此,至少您的 Stream/LazyList 有第一个元素(已评估),即 1 from

1 #:: fibbonaciNumbers.scanLeft...

列表中的第二个元素是 scanLeft 中的 1 ...然后 scanLeft 接管以生成其余元素 2、3、5 ...但仅在需要时才对它们进行评估。但是什么时候需要它们?... 你打电话时

println("The result is " + fibbonaciNumbersSum(4000000))

这将触发评估

fibbonaciNumbers.takeWhile(_ <= limit).filter(_ % 2 == 0).sum

因此,只要 Stream / LazyList 中的每个元素小于限制,就会对它们进行评估,并且将完成过滤和求和。

于 2019-06-14T20:54:58.627 回答