有一种模式会反复出现,而我还无法完全理解它,例如下面的code计算isPrime

class S99Int(val start: Int) {
  import S99Int._
  def isPrime: Boolean =
    (start > 1) && (primes takeWhile ( _ <= Math.sqrt(start) ) forall ( start % _ != 0 ))
}

object S99Int {
  implicit def int2S99Int(i: Int): S99Int = new S99Int(i)
  val primes = Stream.cons(2, Stream.from(3, 2) filter { _.isPrime })
}
import S99Int._

24 isPrime        //returns false

我不明白的是:primes中的filter使用isPrime。但是,def isPrime再次使用相同的primes来获取元素。难道不是像一个无限循环,其中一件事要问另一件事,然后又把那件事再次问给自己。虽然代码可以完美运行。

最佳答案

懒惰地评估Scala中的流。这意味着仅计算直到您实际需要的最后一个值。这对于您的主要示例意味着什么:
isPrime不使用整个primes流,而仅使用其中一部分:

(primes takeWhile ( _ <= Math.sqrt(start) )

它仅使用小于您要测试的数字平方根的部分(以及下一个,因为您必须对其进行评估才能看到它太大)。现在,primes再次为这些较小的数字之一调用isPrime时,primes的所需部分甚至更小。这一直持续到您达到初始2。

将其视为相互递归的函数:
  • isPrime
  • primes可被视为primesUpTo(n: Int)

  • 接着:
    class S99Int(val start: Int) {
      import S99Int._
      def isPrime: Boolean =
        (start > 1) && (S99Int.primesUpTo(math.sqrt(start).toInt) forall ( start % _ != 0 ))
    }
    
    object S99Int {
      implicit def int2S99Int(i: Int): S99Int = new S99Int(i)
      def primesUpTo(n: Int): IndexedSeq[Int] = {
        if (n >= 2) 2 +: (3 to n) filter { _.isPrime }
        else IndexedSeq.empty
      }
    }
    
    Stream唯一为您实现的功能是从primesUpTo(n: Int)缓存值,以便仅计算一次,并使函数程序员更加了解UpTo表达式。

    关于scala - 了解流,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16153826/

    10-12 23:59