Я начал изучать Clojure несколько дней назад и написал этот код, который разлагает числа на множители. Как мне сделать это лучше? Есть ли способ избежать этого с помощью цикла? Это то, как я должен кодировать в Clojure?
(defn classify [n]
(loop [n n
i 2
f []]
(cond
(= n i) (conj f i)
(= (mod n i) 0) (recur (/ n i) 2 (conj f i))
:else (recur n (inc i) f))))
1 ответ
Может быть, более функциональный способ выразить ваш алгоритм …
(defn classify [n]
(letfn [(factors-from [i from]
(cond
(= i 1) '()
(zero? (mod i from)) (cons from (factors-from (quot i from) from))
:else (recur i (inc from))))]
(factors-from n 2)))
- Локальная функция
factors-from
играет рольloop
. - Рекурсивный вызов, когда мы нашли фактор, спасает нас, передавая последовательность факторов в качестве параметра.
- Мы используем
quot
вместо/
для деления, так как это проще. - Конечный корпус
1
вместоfrom
. Это дает правильный ответ на пустой список факторов, когдаn
является1
. - Нормальный случай, когда мы не находим множитель, — это рекурсия с прямым хвостом, поэтому может быть
recur
.
Нет опасности исчерпать пространство стека, так как наименьшее число, которое могло бы сделать это, составляет около 2 ^ 10000, что намного превосходит все, с чем могла бы справиться длинная арифметика.