2024年Clojure状态调查!中分享您的想法。

欢迎!有关该功能的更多信息,请参阅关于页面。

0
core.async

运行此代码最终会抛出OOME

`
(let [c (a/chan)]
(a/go (while (a/<! c)))
(a/go

(when-some [xs (range)]
  (doseq [x xs]
    (a/>! c x)))))

`

这个(用{{let}}而不是{{when-some}})可以正常工作

`
(let [c (a/chan)]
(a/go (while (a/<! c)))
(a/go

(let [xs (range)]
  (doseq [x xs]
    (a/>! c x)))))

`

在前者中,range序列被存储在堆中(在go块的状态数组中),并且在doseq迭代期间一直保留,尽管在循环初始化后不再需要。
在后者中,range序列被存储在栈上,因此编译器能够执行其局部清除魔法。

这种行为可能发生在跨越多个ssablock的每个值上。

3个答案

0

由:alexmiller 评论

问题实际上是不是当-some实际上是一个let,而你正在保留无限range的头在let中?

0

由:leonoel 评论

我使用更简单的示例更新了描述。
问题发生是因为let绑定包装了一个控制流表达式。这实际上将值从栈移到堆上,防止编译器清除引用。

0
...