与cond的Clojure循环

时间:2014-04-29 22:00:14

标签: clojure prime-factoring

我正在研究Project Euler问题,其中涉及分解数字,并编写了以下函数来执行此操作。

(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并且我的println语句以奇怪的顺序进行评估。以下是(get-factors 12)的REPL输出,该输出应返回#{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))评估为true,也会触发默认状态。同样,退出条件被命中两次。评估的最后一个案例应该是n = 3,但你可以看到最多n = 5的输出。

我显然做了一些根本错误的事情,但我没有看到什么。 (相关,有没有更好的方法来构建列表?)

2 个答案:

答案 0 :(得分:1)

首先,有一个隐含的"当" (或" if")在任何cond的测试部分中,因此您不应该在该测试中使用when

其次,您使用单个表单when表单作为cond的整个分支,因此,cond没有看到它预期的第二个表单测试是真的。

查看适当的cond

的示例

http://clojuredocs.org/clojure_core/1.2.0/clojure.core/cond

答案 1 :(得分:0)

如果正如其他人所建议的那样,你会删除所有的问题 - whendo以及println - 你的程序是有效的!

一些建议:

  • 使用quot代替/获取整数商。
  • 您也可以这样开始您的线程宏:(->> value (Math/sqrt) ... )
  • 使用:else,而非:default或其他任何内容在cond中引入catch-all条款。