运行此代码最终会抛出 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 块的每个值,都可能出现这种行为。