Работя по а Проект Ойлер проблем, който включва факторинг номера и са написали следната функция за това.
(defn get-factors [value]
(let [max-factor (->> (Math/sqrt value)
(Math/floor)
(Math/round))
ifactors #{}]
(loop [n 2 factors ifactors]
(do
(println (format ">> N: %d, Factors: %s" n factors))
(cond
(when (> n max-factor) ; exit of we have passed the max-factor
(do
(println (format "--Exiting(%d): %s" n factors))
factors)) ; return factors
(when (= 0 (mod value n)); have we found a factor?
(do
(println (format"--Factor(%d)" n))
(recur (inc n) (conj factors n (/ value n))))) ; recurse: add _n_ and reciprocal _n_ to list
:default (do ; otherwise
(println (format"--default(%d): %s" n (= 0 (mod value n))))
(recur (inc n) factors)) ; recurse: increment _n_, dont modify factors
)))))
Функцията обаче се връща nil
и моите отчети са оценени по странен ред. Ето резултата от REPL за (get-factors 12)
, който трябва да се върне #{2,3,4,6}
:
>> N: 2, Factors: #{}
--default(2): true
>> N: 3, Factors: #{}
--default(3): true
>> N: 4, Factors: #{}
--Exiting(4): #{}
--Factor(4)
>> N: 5, Factors: #{3 4}
--Exiting(5): #{3 4}
Както можете да видите, състоянието по подразбиране се удря, въпреки че (= 0 (mod value n))
от предишния случай се оценява до вярно. Също така изходното условие се удря два пъти. Последният оценен случай трябва да бъде за n = 3, но можете да видите изход до n = 5.
Очевидно правя нещо основно погрешно, но не виждам какво. (Свързан ли е, има ли по-добър начин да се направи списък?)
Отговори:
1 за отговор № 1Първо, има имплицитна "кога" (или "ако") в тестовата част на която и да е cond
така че не трябва да използвате when
себе си в този тест.
Второ, използвате единствен формуляр, a when
форма, като целия клон на cond
, следователно, cond
не вижда втората форма, която очаква, когато тестът е вярно.
Вижте този пример за правилното cond
:
http://clojuredocs.org/clojure_core/1.2.0/clojure.core/cond
0 за отговор № 2
Ако, както другите са ви предложили, вие изваждате всички несправедливи - when
пясък do
пясък println
s - вашата програма работи!
Няколко предложения:
- употреба
quot
вместо/
за да получите цяло число коефициент. - Също така може да започнете макрото ви за теглене по следния начин:
(->> value (Math/sqrt) ... )
. - употреба
:else
, не:default
или каквото и да е друго, за да въведете клаузата за улов във вашатаcond
.