Clojure中的相互递归定义

Abh*_*kar 6 recursion clojure definition

如何在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
Run Code Online (Sandbox Code Playgroud)

我把它翻译成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)
Run Code Online (Sandbox Code Playgroud)

但是在Clojure REPL中逐一编写定义给出了

java.lang.Exception: Unable to resolve symbol: is-prime in this context (NO_SOURCE_FILE:8)
Run Code Online (Sandbox Code Playgroud)

之后我写的(def primes (cons 2 (filter is-prime odds))).

有没有办法在Clojure中做相互递归定义?

G__*_*G__ 8

您需要(declare is-prime)在第一次引用它之前.

这被称为"前向声明".


kot*_*rak 5

格雷格的答案是正确的。但是,您必须重新排列代码:(def odds ...) (declare primes) (defn prime-divisors ...) (defn prime? ...) (def primes ...)。这应该可以解决问题。

问题是素数的定义不是函数。它会立即执行,因此尝试取消引用prime?尚未绑定的Var。因此,例外。重新安排应该注意这一点。

(免责声明:我没有检查代码是否可以重新安排。)

而且我认为prime?已经坏了。(prime? 2)应该给false,不?

  • 2是质数。唯一的因素是2(自身)和1。 (4认同)