How do I do mutually recursive definitions in Clojure?
Here is a code in Scala to find prime numbers which uses recursive definitions:
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
I translated this to 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)
But writing the definitions in the Clojure REPL one by one gives
java.lang.Exception: Unable to resolve symbol: is-prime in this context (NO_SOURCE_FILE:8)
after I write (def primes (cons 2 (filter is-prime odds)))
.
Is there a way to do mutually recursive definitions in Clojure?
You need to (declare is-prime)
before the first time you reference it.
This is referred to as a "forward declaration".
Greg's answer is correct. However you have to rearrange your code: (def odds ...) (declare primes) (defn prime-divisors ...) (defn prime? ...) (def primes ...)
. This should do the trick.
The problem is, that the definition of primes is not a function. It is executed immediately and hence tries to dereference the prime?
Var which is not bound, yet. Hence the exception. Re-arranging should take care of that.
(Disclaimer: I haven't checked that the code works with the re-arrangement.)
And I think prime?
is broken. (prime? 2)
should give false
, no?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With