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 撰写

此处的提议是捕捉递归序列实现(即当尝试计算懒序列的主体时尝试访问同一序列)并抛出异常。

当前,在这种情况下发生时,对序列的递归访问将返回 nil。这导致似乎正常工作的代码产生错误结果,甚至可能出于幸运而产生正确的结果的错误代码(请参阅 https://groups.google.com/d/topic/clojure/yD941fIxhyE/discussion 中的此类示例)。

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

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

当前
|状态|f|sv|s|
| :-- | :-- | :-- | :-- | :-- |
|未实现|非空|null|null|
|实现|空|null|任何内容|
|正在实现/从fn.invoke处递归调用|非空|null|null|
|正在实现/从ls.sval处递归调用|null|null|null|
注意,"正在实现"状态与未实现或实现重叠。
(注:"任何内容"包括null)

使用补丁
|状态|f|sv|s|
| :-- | :-- | :-- | :-- | :-- |
|未实现|非空|null|null|
|实现|空|null|除了这个以外的任何内容|
|正在实现|空|null|这个|

0

评论者:jafingerhut

最后一个评论,Christophe,对我来说明确了解这个想法。能否在补丁中添加与这种内容相似的评论?

0

评论由:cgrand 撰写

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

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

CLJ-1119也被这个补丁解决。

0

评论者:jafingerhut

补丁clj-457-3.diff与Christophe的CLJ-457-2.diff相同,但已更新,不再与11月22日为CLJ-949做出的提交冲突,该提交基本上取消了sval()方法中的try/catch。它通过了测试,我没有看到任何问题,但如果Christophe也能看一下就好了。

0

评论者:alexmiller

已经无法复现。

0
by
_评论由:bronsa_...

Alex,由于 `(range)` 不再产生分块序列,因此发布的示例无法再重现。
另一方面,`(range n)` 通过在问题描述的代码示例中将 `(range)` 替换为类似于 `(range Long/MAX_VALUE)` 的内容可以重新出现该错误




Clojure 1.8.0-master-SNAPSHOT
用户=> (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
用户=> (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](https://clojure.atlassian.net/browse/CLJ-457)(由alex+import报告)
...