请在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
0

评论由:aaron 撰写

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

0

评论由:richhickey 撰写

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

0

评论由:aaron 撰写

Stu,我们讨论过这个问题,但我记不清楚具体是什么问题。

0

评论由:cgrand 撰写

附加了一个临时修补程序。
有现有的代码被这样的修补程序(如 Aaron Bedra 所提到)破坏的例子吗?

0

评论由:richhickey 撰写

该修补程序意图做什么?我们只有问题描述和代码。请列出计划,而不是让我们去解析这个修补程序。

作为首要原则,我不想让 Clojure 承诺递归定义的值是可能的。

0

评论由: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|
| :-- | :-- | :-- | :-- | :-- |
|未实现|非空|空|空|
|已实现|空|空|除这个以外的任何值|
|正在实现|空|空|这个值|

0
by

评论者:jafingerhut

最后的评论,Christophe,至少对我解释了这个想法,任何可能添加相似内容的评论作为补丁的一部分吗?

0
by

评论由:cgrand 撰写

包含预期状态说明的新补丁。
注意:我对状态表进行了整理。

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

此补丁也修复了 CLJ-1119。

0
by

评论者:jafingerhut

clj-457-3.diff 补丁与 Christophe 的 CLJ-457-2.diff 相同,但已更新以不再与 2013 年 11 月 22 日为 CLJ-949 提交的补丁冲突,该补丁本质上删除了 method sval() 中的 try/catch。它通过了测试,我没有看到什么问题,但是如果 Christophe 能看一下就好了。

0
by

评论者:alexmiller

无法复现

0
by
_评论者: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 报告)
...