2

この怠惰な素数シーケンスの定義が非終了を引き起こす理由がわかりません。私が取得したスタック トレースはあまり役に立ちません (clojure に関する私の不満の 1 つは、スタック トレースがわかりにくいことです)。

(declare naturals is-prime? primes)

(defn naturals
  ([] (naturals 1))
  ([n] (lazy-seq (cons n (naturals (inc n))))))

(defn is-prime? [n]
  (not-any? #(zero? (rem n %))
                (take-while #(> n (* % %)) (primes))))

(defn primes
  ([] (lazy-seq (cons 2 (primes 3))))
  ([n] (let [m (first (filter is-prime? (naturals n)))]
         (lazy-seq (cons m (primes (+ 2 m)))))))

(take 10 (primes)) ; this results in a stack overflow error
4

3 に答える 3

0

問題は、「is-primes?」を使用している「素数」関数を計算することを知ることです。関数を使用して、「is-prime?」を計算します。「(素数)」を使用している関数、したがってスタックオーバーフロー。

"(primes 3)" を計算するには、"(first (filter is-prime? (naturals 3)))" を計算する必要があります。これは "(is-prime? 1)" を呼び出します。 "(primes)" を呼び出すと、"(primes 3)" が呼び出されます。言い換えれば、あなたがやっている:

user=> (declare a b)
#'user/b
user=> (defn a [] (b))
#'user/a
user=> (defn b [] (a))
#'user/b
user=> (a)
StackOverflowError   user/b (NO_SOURCE_FILE:1)

素数を生成する方法を確認するには: Clojure での素数の高速生成

于 2012-07-11T12:03:57.103 に答える
0

の実行を開始primesしましょう。明確にするために、魔法のように実現seqします。naturalsそれは正しく怠惰なので無視します:

 > (magically-realise-seq (primes))
=> (magically-realise-seq (lazy-seq (cons 2 (primes 3))))
=> (cons 2 (primes 3))
=> (cons 2 (let [m (first (filter is-prime? (naturals 3)))]
             (lazy-seq (cons m (primes (+ 2 3))))))
=> (cons 2 (let [m (first (filter
                            (fn [n]
                              (not-any? #(zero? (rem n %))
                                            (take-while #(> n (* % %)) (primes))))) 
                            (naturals 3)))]
             (lazy-seq (cons m (primes (+ 2 3))))))

is-prime?最後にaを代入しました。これが再度呼び出され、要素を引き出すときに少なくとも 1 回認識されるfnことがわかります。これにより、ループが発生します。primestake-while

于 2012-07-11T12:04:07.550 に答える