我无法弄清楚为什么惰性素数序列的这个定义会导致非终止。我得到的堆栈跟踪不是很有帮助(我对clojure的一个抱怨是钝的堆栈跟踪)。
(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
答案 0 :(得分:0)
问题是要知道计算“素数”函数你正在使用“是素数”吗?函数,然后计算“是素数?”函数你使用“(素数)”,因此堆栈溢出流量。
所以要计算“(素数3)”,你需要计算“(首先(过滤器是素数?(自然3)))”,这将称为“(is-prime?1)” ,它称为“(素数)”,它又称为“(素数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)
要了解如何生成素数:Fast Prime Number Generation in Clojure
答案 1 :(得分: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?
替换为最后的fn
- 您可以看到primes
将再次被调用,并至少实现一次为take-while
拉出元素。这将导致循环。
答案 2 :(得分:0)
我认为问题是,你在构建它之前尝试使用(素数)。
像这样更改is-prime?
可解决问题:
(defn is-prime? [n]
(not-any? #(zero? (rem n %))
(take-while #(>= n (* % %)) (next (naturals)))))
(注意,我已将>
更改为>=
,否则它会给出4是素数。它仍然表示1是素数,这不是真的,如果你可能会导致问题在其他地方使用is-prime?
。