首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Scala流计算抛出StackOverflowError

Scala流计算抛出StackOverflowError
EN

Stack Overflow用户
提问于 2016-03-30 22:37:03
回答 1查看 97关注 0票数 2

为什么这个代码段执行会导致StackOverflowError

代码语言:javascript
复制
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之前的点):

代码语言:javascript
复制
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
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-03-30 23:03:30

括号将使这里的执行顺序更加明显。以下两个primes定义等价于OP中各自的对应项。

代码语言:javascript
复制
// 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)
})

好吧,第一个怎么了?首先通过创建流(2 #:: Stream.from(3, 2))来定义它,然后对其进行过滤。让我们尝试访问第一个元素:

代码语言:javascript
复制
primes.head

这实际上也会产生堆栈溢出。下面是发生的事情:

  1. head试图访问primes的第一个元素。
  2. 必须对照2谓词检查第一个元素filter
  3. 要检查谓词,我们必须递归地访问primes
  4. 我们尝试接受primes的第一个元素,它必须在2上运行filter谓词。
  5. 重复第三步。

...Which导致堆栈溢出。

第二个示例没有遇到这个问题,因为Stream (2)的头没有被过滤,所以在这一步中没有递归来检查2是否真的存在。换句话说,在第二个例子中,很明显,2Streamhead。在第一个示例中,必须通过检查head来计算Streamfilter,但要做到这一点,必须在无限递归循环中引用自身。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36320975

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档