我在哪里失去了懒惰?
Where am I losing lazyness?
我正在尝试编写一个惰性迭代素筛。
筛的每次迭代由
表示
[[primes] (candidates) {priority-map-of-multiples-of-primes}]
我有一个函数 sieve-next-candidate-update,它会愉快地进行筛选迭代,检查下一个候选对象,并适当地更新所有三个组件。
这样使用:
(take 3 (iterate sieve-next-candidate-update [[2] (range 3 13 2) (priority-map 2 2)]))
我得到了我期望的结果:
([[2] (3 5 7 9 11) {2 2}]
[[2 3] (5 7 9 11) {3 3, 2 4}]
[[2 3 5] (7 9 11) {5 5, 2 6, 3 6}])
但是,当我 运行 它通过 reduce 删除没有找到新素数的迭代时,它会尝试处理整个序列,但是我定义了初始候选列表(如果我使用迭代)。
(take 3
(reduce (fn [old-primes-sieves new-sieve]
(prn (str "reduce fn called with new sieve" new-sieve))
(if (= (last (first (last old-primes-sieves))) ; I'm aware I don't want last in the final version
(last (first new-sieve)))
old-primes-sieves
(conj old-primes-sieves new-sieve)))
[]
(iterate sieve-next-candidate-update [[2] (range 3 13 2) (priority-map 2 2)])))
产出
"reduce fn called with new sieve[[2] (3 5 7 9 11) {2 2}]"
"reduce fn called with new sieve[[2 3] (5 7 9 11) {3 3, 2 4}]"
"reduce fn called with new sieve[[2 3 5] (7 9 11) {5 5, 2 6, 3 6}]"
"reduce fn called with new sieve[[2 3 5 7] (9 11) {7 7, 2 8, 3 9, 5 10}]"
"reduce fn called with new sieve[[2 3 5 7] (11) {3 9, 2 10, 5 10, 7 14}]"
"reduce fn called with new sieve[[2 3 5 7 11] nil {11 11, 2 12, 3 12, 7 14, 5 15}]"
然后在这种有限的情况下抛出 NullPointerException。
我在哪里失去了懒惰?
reduce is not lazy - it will try to iterate whole infinite sequence (iterate sieve-next-candidate-update [[2] (range 3 13 2) (priority-map 2 2)])
. You can use reductions 代替。
顺便说一下,可以在 clojure.contrib here 中找到有效的无限素数序列的好例子。
我正在尝试编写一个惰性迭代素筛。
筛的每次迭代由
表示[[primes] (candidates) {priority-map-of-multiples-of-primes}]
我有一个函数 sieve-next-candidate-update,它会愉快地进行筛选迭代,检查下一个候选对象,并适当地更新所有三个组件。
这样使用:
(take 3 (iterate sieve-next-candidate-update [[2] (range 3 13 2) (priority-map 2 2)]))
我得到了我期望的结果:
([[2] (3 5 7 9 11) {2 2}]
[[2 3] (5 7 9 11) {3 3, 2 4}]
[[2 3 5] (7 9 11) {5 5, 2 6, 3 6}])
但是,当我 运行 它通过 reduce 删除没有找到新素数的迭代时,它会尝试处理整个序列,但是我定义了初始候选列表(如果我使用迭代)。
(take 3
(reduce (fn [old-primes-sieves new-sieve]
(prn (str "reduce fn called with new sieve" new-sieve))
(if (= (last (first (last old-primes-sieves))) ; I'm aware I don't want last in the final version
(last (first new-sieve)))
old-primes-sieves
(conj old-primes-sieves new-sieve)))
[]
(iterate sieve-next-candidate-update [[2] (range 3 13 2) (priority-map 2 2)])))
产出
"reduce fn called with new sieve[[2] (3 5 7 9 11) {2 2}]"
"reduce fn called with new sieve[[2 3] (5 7 9 11) {3 3, 2 4}]"
"reduce fn called with new sieve[[2 3 5] (7 9 11) {5 5, 2 6, 3 6}]"
"reduce fn called with new sieve[[2 3 5 7] (9 11) {7 7, 2 8, 3 9, 5 10}]"
"reduce fn called with new sieve[[2 3 5 7] (11) {3 9, 2 10, 5 10, 7 14}]"
"reduce fn called with new sieve[[2 3 5 7 11] nil {11 11, 2 12, 3 12, 7 14, 5 15}]"
然后在这种有限的情况下抛出 NullPointerException。
我在哪里失去了懒惰?
reduce is not lazy - it will try to iterate whole infinite sequence (iterate sieve-next-candidate-update [[2] (range 3 13 2) (priority-map 2 2)])
. You can use reductions 代替。
顺便说一下,可以在 clojure.contrib here 中找到有效的无限素数序列的好例子。