如何在Clojure中进行相互递归定义?
以下是Scala中用于查找使用递归定义的素数的代码:
val odds: Stream[Int] = cons(3, odds map { _ + 2 })
val primes: Stream[Int] = cons(2, odds filter isPrime)
def primeDivisors(n: Int) =
primes takeWhile { _ <= Math.ceil(Math.sqrt(n))} filter { n % _ == 0 }
def isPrime(n: Int) = primeDivisors(n) isEmpty
primes take 10
我把它翻译成Clojure:
(def odds (iterate #(+ % 2) 3))
(def primes (cons 2 (filter is-prime odds)))
(defn prime-divisors [n]
(filter #(zero? (mod n %))
(take-while #(<= % (Math/ceil (Math/sqrt n)))
primes)))
(defn is-prime [n] (empty? (prime-divisors n)))
(take 10 primes)
但是在Clojure REPL中逐一编写定义会给出
java.lang.Exception: Unable to resolve symbol: is-prime in this context (NO_SOURCE_FILE:8)
在我写(def primes (cons 2 (filter is-prime odds)))
之后。
有没有办法在Clojure中做相互递归的定义?
答案 0 :(得分:7)
在您第一次引用它之前,您需要(declare is-prime)
。
这被称为“前向声明”。
答案 1 :(得分:5)
(def odds ...) (declare primes) (defn prime-divisors ...) (defn prime? ...) (def primes ...)
。这应该可以解决问题。
问题是,素数的定义不是函数。它立即执行,因此尝试取消引用尚未绑定的prime?
Var。因此例外。重新安排应该照顾好。
(免责声明:我没有检查代码是否适用于重新安排。)
我认为prime?
已被打破。 (prime? 2)
应该false
,不是吗?