Как сделать мой код Clojure более «функциональным»?

Я начал изучать 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 ответ
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, что намного превосходит все, с чем могла бы справиться длинная арифметика.

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *