我正在处理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
答案 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