为什么此代码段执行会导致Series
:
StackOverflowError
虽然此代码段工作正常(请参阅lazy val primes: Stream[Int] = 2 #:: Stream.from(3, 2) filter { pc =>
primes.takeWhile(x => x * x <= pc) forall (p => pc % p != 0)
}
primes.take(5).last
之前的点):
filter
答案 0 :(得分:6)
括号将使执行顺序更加明显。 // fails with stack overflow
lazy val primes: Stream[Int] = (2 #:: Stream.from(3, 2)) filter { pc =>
primes.takeWhile(x => x * x <= pc) forall (p => pc % p != 0)
}
// succeeds
lazy val primes: Stream[Int] = 2 #:: (Stream.from(3, 2).filter { pc =>
primes.takeWhile(x => x * x <= pc) forall (p => pc % p != 0)
})
的以下两个定义等同于OP中的各自定义。
(2 #:: Stream.from(3, 2))
好的,那么第一个错误是什么?首先通过创建流primes.head
,然后对其进行过滤来定义它。让我们尝试访问第一个元素:
head
这实际上也会产生堆栈溢出。这里发生了什么:
primes
尝试访问2
的第一个元素。filter
谓词检查第一个元素primes
。primes
。filter
的第一个元素,该元素必须在2
上运行Stream
谓词。......这会导致堆栈溢出。
第二个示例没有遇到此问题,因为2
(2
)的头部未被过滤,因此在该步骤没有递归检查是否{{ 1}}真的存在与否。换句话说,在第二个示例中,很明显2
是head
的{{1}}。在第一个示例中,Stream
的{{1}}必须通过检查head
来计算,但为了这样做,在无限递归循环中引用它自己。