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中的.while循环中的.sval和.sval中的.invoke)之前对LazySeq状态(f、sv和s字段)进行修改,以便在重入时,LazySeq的状态是连贯的,并且能够表达该序列已经被计算的事实。

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

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

使用补丁后
|状态|f|sv|s|
| :-- | :-- | :-- | :-- | :-- |
未实现|非空|空|空|
已实现|空|空|除了这个之外任何|
正在实现|空|空|这个|

0

评论者:jafingerhut

那个最后的评论,Christophe,至少对我不失为一个很好的解释。能否有类似内容的评论作为补丁的一部分添加?

0

由 cgrand 发布的评论

新补丁附带解释预期状态的注释。
注意:我已经整理了状态表。

在调用用户代码(在sval中为f.invoke(),间接地在seq中为((LazySeq)ls).sval(),甚至在seq中的RT.seq()),确保LazySeq状态处于以下状态之一:// // 状态 f sv // ================================ // 未实现 非空 空 // 已实现 空 空 // 正在实现 空 这个

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)`的`(range n)`就足以重现错误。




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 报告)
...