评论由:cgrand 发布
这里的提案是捕捉递归seq实现(即当计算lazy-seq的主体时尝试访问同一seq时),并抛出异常。
目前当这种情况下发生时,递归访问seq返回nil。这导致代码似乎在正常工作,但实际上产生错误结果,或者甚至错误的代码也由于运气而产生了正确的结果(参见https://groups.google.com/d/topic/clojure/yD941fIxhyE/discussion中的示例)。
因此,这个补丁会调整LazySeq状态(f, sv 和 s 字段)在所有可能递归调用的之前(.seq 中的 .sval 和.sval中的 .invoke),以便在重新进入时,LazySeq 状态是一致的,并且能传达出seq已经被计算的事实。
目前递归调用可能会发现 f 和 sv 被清除,并得出计算已完成且结果在 s 中的结论,尽管 s 仍未受到影响。
目前:
|状态|f|sv|s|
| :-- | :-- | :-- | :-- | :-- |
|未实现|非空|空|空|
|实现|空|空|任何内容|
|被实现/从fn.invoke的递归调用|非空|空|空|
|被实现/从ls.sval的递归调用|空|空|空|
注意,“被实现”状态与“未实现”或“已实现”重叠。
(注意:“任何内容”包括空)
有了这个补丁
|状态|f|sv|s|
| :-- | :-- | :-- | :-- | :-- |
|未实现|非空|空|空|
|实现|空|空|除了这个以外的任何内容|
|正在实现|空|空|这个|