functional-programming - 惰性序列中 "Lose your head"的解释

标签 functional-programming clojure lazy-evaluation jvm-languages

在 Clojure 编程语言中,为什么这段代码表现出色?

(let [r (range 1e9)] [(first r) (last r)])

虽然这个失败了:

(let [r (range 1e9)] [(last r) (first r)])

我知道这是关于“失去理智”的建议,但你能向我解释一下吗?我还没来得及消化。

更新:
很难选出正确的答案,两个答案的信息量惊人。
注意:代码片段来自“The Joy of Clojure”。

最佳答案

详细说明dfanRafał的答案,我花时间用 YourKit 运行这两个表达式分析器。

看到 JVM 的工作真是令人着迷。第一个程序对 GC 非常友好,以至于 JVM 在管理内存方面确实表现出色。

我画了一些图表。

GC 友好:(let [r (range 1e9)] [(first r) (last r)])

enter image description here

该程序运行时内存非常低;总体而言,不到6兆字节。如前所述,它对 GC 非常友好,它会进行大量回收,但只使用很少的 CPU。

头部固定器:(let [r (range 1e9)] [(last r) (first r)])

enter image description here

这个非常消耗内存。它的 RAM 高达 300 MB,但这还不够,程序无法完成(JVM 不到一分钟后就终止了)。 GC 占用了 90% 的 CPU 时间,这表明它拼命地尝试释放任何可以释放的内存,但找不到任何内存(收集到的对象很少甚至没有)。

编辑第二个程序内存不足,从而触发了堆转储。对此转储的分析表明,70% 的内存是 java.lang.Integer 对象,无法收集。这是另一个屏幕截图:

enter image description here

关于functional-programming - 惰性序列中 "Lose your head"的解释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5698122/

相关文章:

clojure - clojure 映射和关键字如何成为一个函数

clojure - 无法在 Clojure 中定义类?

python - zip_longest 没有填充值

clojure - 从列表中使用 Noir 生成 img 标签

clojure - 重用多方法的解构

r - 使用 dplyr 编写函数时的惰性求值

f# - 功能范例中的可插拔性

javascript - JavaScript 提供了哪些函数式编程方面的子集和类似 Lisp 的特性?

io - 在haskell中读取大文件?

ocaml - OCaml 如何在运行时表示惰性值?