-->

懒惰-SEQ和堆栈溢出为无穷序列(lazy-seq and stack overflow for i

2019-10-22 06:20发布

我想展现给非FP程序员懒惰序列或懒惰评估的重要性。 我写了这个实施黄金一代的显示概念:

(defn primes-gen [sieve]
  (if-not (empty? sieve)
    (let [prime (first sieve)]
      (cons prime
            (lazy-seq (primes-gen
                       (filter (fn [x]
                                 (not= 0 (mod x prime)))
                               (rest sieve))))))))

;;;;; --------- TO SHOW ABOUT THE LAZY-THINGS 
;; (take 400 (primes-gen (iterate inc 2)))
;; (take 400 (primes-gen (range 2 1000000000000N)))

不过,我得到堆栈溢出异常,如果我给任何更大的价值take

堆栈是:

user> (pst)
StackOverflowError 

    clojure.core/range/fn--4269 (core.clj:2664)
    clojure.lang.LazySeq.sval (LazySeq.java:42)
    clojure.lang.LazySeq.seq (LazySeq.java:60)
    clojure.lang.RT.seq (RT.java:484)
    clojure.core/seq (core.clj:133)
    clojure.core/filter/fn--4226 (core.clj:2523)
    clojure.lang.LazySeq.sval (LazySeq.java:42)
    clojure.lang.LazySeq.seq (LazySeq.java:60)
    clojure.lang.RT.seq (RT.java:484)
    clojure.core/seq (core.clj:133)

看来, filter的thunk越来越积累。 但是,如果DO (doall (filter ...然后我不就能够处理无限序列,即(take 1000 (primes-gen (iterate inc 2)))将不再工作。

什么是做正确的方式?

Answer 1:

你的分析是对现货:你嵌套过滤器过多。 您应修改主要根采取有两个参数:该组已知的素数和考生。 请参见我的博客上一些其他的想法贯彻Erathostenes'筛子 。

更新:所以你叠滤波器在过滤器和在某些时候,当你想获取新的候选堆太大。

你必须将所有过滤器合并成一个单一的(或合理数量)通。 这是因为过滤器是很均匀很容易。 所以我更换一个集合持有已知质数叠滤波器。

(defn primes-gen
 ([candidates] (primes-gen candidates []))
 ([candidates known-primes]
  (lazy-seq ; I prefer having the lazy-seq up here
    (when-first [prime candidates] ; little known macro
      (let [known-primes (conj known-primes prime)]
        (cons prime
          (primes-gen
            (drop-while (fn [n] (some #(zero? (mod n %)) known-primes)) candidates)
             known-primes)))))))


Answer 2:

一个可能的解决方案会偷懒序列内部移动发电机功能。 例如(摘自这里 ):

(def primes
  (concat
   [2 3 5 7]
   (lazy-seq
    (let [primes-from
          (fn primes-from [n [f & r]]
            (if (some #(zero? (rem n %))
                      (take-while #(<= (* % %) n) primes))
              (recur (+ n f) r)
              (lazy-seq (cons n (primes-from (+ n f) r)))))
          wheel (cycle [2 4 2 4 6 2 6 4 2 4 6 6 2 6  4  2
                        6 4 6 8 4 2 4 2 4 8 6 4 6 2  4  6
                        2 6 6 4 2 4 6 2 6 4 2 4 2 10 2 10])]
      (primes-from 11 wheel)))))


文章来源: lazy-seq and stack overflow for infinite sequences