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中的示例)。

因此,这个补丁将对LazySeq状态(f、sv和s字段)的修改移动到所有潜在的递归方法调用(.seq中的.sval和.sval中的.invoke)之前,以确保在重新进入时,LazySeq的状态是一致的,并能传达seq已经在被计算的事实。

目前,递归调用可能在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_ 提供

Alex,所发布的示例已无法复现,因为 `(range)` 不再生成分块序列。
另一方面,将 `(range)` 替换为如 `(range Long/MAX_VALUE)` 这样的内容,在工单描述中的代码示例中就足够使错误重现




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
参考: https://clojure.atlassian.net/browse/CLJ-457(由 alex+import 报告)
...