LazyList .scanLeft () вызывается в пустом списке - PullRequest
4 голосов
/ 14 июня 2019

Я занимался некоторыми проблемами Эйлера в Scala, когда нашел очень элегантное решение проблемы # 2. Однако у меня есть некоторые проблемы с пониманием, почему это работает. Насколько я могу судить, требуется 1 и добавляется к fibbonaciNumbers.scanLeft(1)(_ + _) для инициализации того же массива. Как можно вызвать scanLeft() on и 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
}

1 Ответ

2 голосов
/ 14 июня 2019

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 из

1 #:: fibbonaciNumbers.scanLeft...

Вторым элементом в списке является 1 из scanLeft ... и затем scanLeft вступает во владение, чтобы сгенерировать остальные элементы 2, 3, 5 ... но они будут оцениваться только при необходимости. Но когда они нужны? ... когда вы звоните

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

и это вызовет оценку

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

Таким образом, каждый элемент в Stream / LazyList будет оцениваться при условии, что они меньше предела, и фильтрация и суммирование будут выполнены.

...