yur*_*ura 6 scala scala-collections
我有以下简单的代码
def fib(i:Long,j:Long):Stream[Long] = i #:: fib(j, i+j)
(0l /: fib(1,1).take(10000000)) (_+_)
Run Code Online (Sandbox Code Playgroud)
它会抛出OutOfMemmoryError异常.我无法理解为什么,因为我认为所有部分都使用常量内存,即惰性评估流和foldLeft ...
这些代码也不起作用
fib(1,1).take(10000000).sum or max, min e.t.c.
Run Code Online (Sandbox Code Playgroud)
如何正确实现无限流并对其进行迭代操作?
Scala版本:2.9.0
另外scala javadoc说,foldLeft操作对于流是memmory安全的
/** Stream specialization of foldLeft which allows GC to collect
* along the way.
*/
@tailrec
override final def foldLeft[B](z: B)(op: (B, A) => B): B = {
if (this.isEmpty) z
else tail.foldLeft(op(z, head))(op)
}
Run Code Online (Sandbox Code Playgroud)
编辑:
使用迭代器的实现仍然无用,因为它会抛出$ {domainName}异常
def fib(i:Long,j:Long): Iterator[Long] = Iterator(i) ++ fib(j, i + j)
Run Code Online (Sandbox Code Playgroud)
如何在Scala中正确定义无限流/迭代器?
EDIT2:我不关心int溢出,我只是想了解如何在scala中创建无限流/迭代器等而没有副作用.
使用Stream
而不是使用的原因Iterator
是您不必再次计算系列中的所有小项.但这意味着您需要存储一千万个流节点.不幸的是,它们非常大,因此可能足以溢出默认内存.解决这个问题的唯一现实方法是从更多内存开始(例如scala -J-Xmx2G
).(另外,请注意,你将Long
大幅溢出;斐波纳契系列增长很快.)
PS我想到的迭代器实现是完全不同的; 你不是用连接的单例构建Iterator
的:
def fib(i: Long, j: Long) = Iterator.iterate((i,j)){ case (a,b) => (b,a+b) }.map(_._1)
Run Code Online (Sandbox Code Playgroud)
现在折叠时,可以放弃过去的结果.