用 Haskell 进行函数式思考 http://www.cambridge.org/us/academic/subjects/computer-science/programming-languages-and-applied-logic/thinking-functionally-haskell提供以下代码来计算mean的列表中的Float's.
mean :: [Float] -> Float
mean [] = 0
mean xs = sum xs / fromIntegral (length xs)
理查德·伯德教授评论道:
现在我们准备看看平均值到底出了什么问题:它存在空间泄漏。评估mean [1..1000]
将导致列表在求和后被扩展并保留在内存中,因为有第二个指针指向它,即在计算其长度时。
如果我正确理解这段文字,他的意思是,如果没有指向xs
在长度计算中,则xs
内存本来可以被释放after计算sum
?
我的困惑是 - 如果xs
已经在内存中了,不是吗length
函数只是要使用已经占用的相同内存吗?
我不明白这里的空间泄漏。
The sum
函数不需要将整个列表保存在内存中;它可以一次查看一个元素,然后在移动到下一个元素时忘记它。
因为 Haskell 默认情况下有惰性求值,所以如果你有一个创建列表的函数,sum
可以在整个列表不存在于内存中的情况下使用它(每次生产函数生成一个新元素时,它都会被sum
然后释放)。
完全相同的事情发生在length
.
另一方面,mean
函数将列表提供给两者sum
and length
。所以在评估的过程中sum
,我们需要将列表保存在内存中,以便可以通过以下方式处理它length
later.
[更新]需要明确的是,该列表最终将被垃圾收集。问题是它的停留时间比需要的时间长。在这种简单的情况下,这不是问题,但在对无限流进行操作的更复杂的函数中,这很可能会导致内存泄漏。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)