clojure中的函数递归

时间:2016-11-10 19:52:15

标签: recursion clojure

我正在处理clojure中的递归,我真的不明白。 我做了一个小程序,从here试图找到可以除以1到20之间的所有数字的小数。这是我想要的代码,但必须有一些东西我不会因为它没有工作。 你能帮我个忙吗?谢谢!

(defn smallest [nume index]
(while(not ( = index 0))
    (do
        (cond
            (zero?(mod nume index))(let [dec' index] (smallest nume index))
            :else (let [inc' nume] (smallest nume index))))))

编辑: 看起来更好loop/recur所以我试了一下:

(loop [nume 20
            index 20]
        (if (= index 0)
        (println nume)
        (if (zero?(mod nume index))
                (recur nume (dec index))
                (recur (inc nume) 20)))))

工作。如果你对结果感到好奇 - > 232792560

2 个答案:

答案 0 :(得分:1)

while没有按照您的想法行事。

在clojure中,一切(好吧,差不多)都是不可变的,这意味着如果index为0,则在同一个上下文中它总是为0。因此循环直到它是1没有意义。

有很多方法可以实现你想要做的事情,第一个,也是最琐碎的(我认为!)给新人,就是理解loop/recur。例如:

(loop [counter 0] 
  (when (< counter 10) 
    (println counter)
    (recur (inc counter))))

在这里,counter被定义为0,它永远不会以通常的方式改变。当您点击recur时,您会将一个新值(在这种情况下为上一个counter的增量)提交到从loop开始的全新迭代,现在只有counter将被绑定到1。

修改:但请注意,此示例将始终返回nil。它仅用于println的副作用。为什么它会返回nil?因为在上一次迭代中,when子句将返回nil。如果你想返回别的东西,你应该使用if并指定你想在最后一次迭代时返回什么。

你应该多阅读一下这个范例,或者做一些像4clojure这样的练习来更好地掌握这个范例。一旦你这样做,你就会以这种方式思考变得更加简单,这种风格的巨大好处将开始出现。

祝你好运!

答案 1 :(得分:0)

这是一个强力实施测试所有数字的条件,如果它们可以被代码中的所有数字除以1到10(请注意(范围1 11)):

(first 
  (filter #(second %) 
          (map (fn[x] [x (every? identity 
                                  (map #(=  0 (mod x %)) 
                                  (range 2 11)))]) 
               (range 1 Integer/MAX_VALUE))))

它的输出是

[2520 true]

不幸的是,对于更大的数字来说,这不是一个好方法。使用(范围1 21),在我的Macbook上等待几分钟后它就无法完成。让我们试试这个:

user=> (defn gcd [a b] (if (zero? b) a (recur b (mod a b))))
#'user/gcd
user=> (reduce (fn[acc n] (if (not= 0 (mod acc n)) (* acc (/ n (gcd n acc))) acc)) 1 (range 1 11))
2520    
user=> (reduce (fn[acc n] (if (not= 0 (mod acc n)) (* acc (/ n (gcd n acc))) acc)) 1 (range 1 21))
232792560