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

欢迎!请查看关于页面,了解更多此平台如何运作的信息。

0
Clojure
如果您使用一个引用同一全局数据变量的惰性序列来定义全局数据变量,那么您将根据构建集合时使用的函数的惰性程度获得不同的结果。

Clojure的惰性序列并不保证支持这一点,但它们不应该返回错误答案。在http://groups.google.com/group/clojure/browse_thread/thread/1c342fad8461602d中给出的示例(如下所示),Clojure不应返回错误数据。一条错误信息会更好,甚至无限循环也比当前的行为更合理。

(相似问题在此报道:https://groups.google.com/d/topic/clojure/yD941fIxhyE/discussion)

(def nums (drop 2 (range Long/MAX_VALUE)))
(def primes (cons (first nums)
             (lazy-seq (->>
               (rest nums)
               (remove
                 (fn [x]
                   (let [dividors (take-while #(<= (* % %) x)
primes)]
                     (println (str "primes = " primes)))
                     (some #(= 0 (rem x %)) dividors))))))))
(take 5 primes)

它打印出来
(primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
2 3 5 7 9)

13 个回答

0

评论由:importer

来自http://www.assembla.com/spaces/clojure/tickets/457转换

0

由:aaron发表的评论

Stu和Rich讨论过将其视为错误,但这将破坏一些现有的代码。

0

由:richhickey发表的评论

关于这个问题有没有具体的疑问?

0

由:aaron发表的评论

Stu,我和你讨论过这个问题,但我记不清具体是什么疑问了。

0

由:cgrand发表的评论

附加了一个临时补丁。
有没有一个现有的代码示例,这个补丁(如Aaron Bedra提到的那样)导致代码损坏?

0

由:richhickey发表的评论

这个补丁的意图是什么?我们只有问题描述和代码。请列出计划,而不是让我们自己解析补丁。

作为一个基本原则,我不想让Clojure承诺递归定义的值是可能的。

0

由:cgrand发表的评论

此处建议捕获递归序列实现(即当计算一个惰性序列的身体尝试访问相同的序列)并抛出异常。

当前,当这种情况发生时,对序列的递归访问返回nil。这导致代码看似工作但产生不正确的结果,或者甚至偶尔产生正确结果的错误代码(参见https://groups.google.com/d/topic/clojure/yD941fIxhyE/discussion中的此类示例)。

因此,这个补丁在所有潜在递归方法调用( seq 的循环中的 .sval 和 .sval 中的 .invoke)之前移动了LazySeq状态的修改(f, sv 和 s 字段),以便在重新进入时,LazySeq的状态是一致的,能够传达序列正在被计算的事实。

目前,递归调用可能会发现f和sv被清空,并得出计算已完成且结果在s中的结论,尽管s尚未受到影响。

目前
|状态|f|sv|s|
| :-- | :-- | :-- | :-- | :-- |
|未实现|非空|null|null|
|已实现|null|null|任何东西|
|正在实现/从fn.invoke的递归调用|非空|null|null|
|正在实现/从ls.sval的递归调用|null|null|null|
注意,“正在实现”状态与“未实现”或“已实现”状态重叠。
(注:“任何东西”包括null)

用这个补丁
|状态|f|sv|s|
| :-- | :-- | :-- | :-- | :-- |
|未实现|非空|null|null|
|已实现|null|null|除了这个以外任何东西|
|正在实现|null|null|这个|

0

评论者:jafingerhut

这个最后的评论,Christophe,至少对我解释了这个想法是很长的一段路。是否有可能将类似内容的评论添加为补丁的一部分?

0

由:cgrand发表的评论

带有注释解释预期状态的新的补丁。
注意:我把状态表整理了一下。

// 在调用用户代码(sval中的f.invoke()和间接的seq中((LazySeq)ls).sval()以及在seq中的RT.seq())之前,确保LazySeq状态处于以下状态之一:// // 状态 f sv// // ==================================// 未实现 非空 null// 已实现 null null// 正在实现 null this

此补丁还解决了CLJ-1119问题。

0

评论者:jafingerhut

补丁clj-457-3.diff与Christophe的CLJ-457-2.diff相同,除了它已更新,不再与2013年11月22日为CLJ-949所做的提交冲突,该提交实际上删除了方法sval()中的try/catch。它通过了测试,我没有发现任何问题,但最好如果Christophe也能看看它。

0

评论者:alexmiller

不再可复现

0
_评论者:bronsa_

亚历克斯,发布的示例现在无法重现,因为`(range)`不再产生分块序列。
另一方面,将`(range)`替换为类似于票务描述中代码示例中的`(range Long/MAX_VALUE)`的`(range n)` sufficient enough to reappear the bug。




Clojure 1.8.0-master-SNAPSHOT
user=> (def nums (drop 2 (range Long/MAX_VALUE)))
#'user/nums
(def primes (cons (first nums)
             (lazy-seq (->>
               (rest nums)
               (remove
                 (fn [x]
                   (let [dividors (take-while #(<= (* % %) x)
primes)]
                     (println (str "primes = " primes)))
                     (some #(= 0 (rem x %)) dividors))))))))
#'user/primes
user=> (take 5 primes)
(primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
primes = (2)
2 3 5 7 9)

0
by
参考: https://clojure.atlassian.net/browse/CLJ-457 (由alex+import报告)
...