Взаимно рекурсивные определения в Clojure

Как я делаю взаимно рекурсивные определения в 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?

6
задан Ken Bloom 9 July 2010 в 14:20
поделиться

2 ответа

Ответ Грега правильный. Однако вам придется изменить код: (def odds ...) (declare primes) (defn prime-divisors ...) (defn prime? ...) (def primes ...). Это должно помочь.

Проблема в том, что определение primes не является функцией. Оно выполняется немедленно и поэтому пытается разыменовать prime? Var, который еще не связан. Отсюда исключение. Переупорядочивание должно решить эту проблему.

(Оговорка: я не проверял, работает ли код с перестановкой.)

И я думаю, что prime? сломан. (prime? 2) должно давать false, нет?

5
ответ дан 8 December 2019 в 18:32
поделиться

Вам необходимо (объявить is-prime) перед первой ссылкой на него.

Это называется «предварительным заявлением».

8
ответ дан 8 December 2019 в 18:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: