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序列存储在栈上,因此编译器能够执行其局部清除魔术。

此行为可能适用于任何跨越多个ssa块的值。

3 答案

0

由:alexmiller

问题实际上是不是当-some实际上是让时,你在let中保留无限范围的头部?

0

由:leonoel

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

0
参考: https://clojure.atlassian.net/browse/ASYNC-219(由leonoel提交)
...