Recursion 在Clojure中递归求三的所有倍数的和
您好,我对Clojure/Lisp编程有点陌生,但我以前在类似C语言中使用过递归,我编写了以下代码,将1到100之间可以除以3的所有数字相加Recursion 在Clojure中递归求三的所有倍数的和,recursion,clojure,lisp,Recursion,Clojure,Lisp,您好,我对Clojure/Lisp编程有点陌生,但我以前在类似C语言中使用过递归,我编写了以下代码,将1到100之间可以除以3的所有数字相加 (defn is_div_by_3[number] (if( = 0 (mod number 3)) true false) ) (defn sum_of_mult3[step,sum] (if (= step 100) sum ) (if (is_div_by_3 step) (sum_of_mult3
(defn is_div_by_3[number]
(if( = 0 (mod number 3))
true false)
)
(defn sum_of_mult3[step,sum]
(if (= step 100)
sum
)
(if (is_div_by_3 step)
(sum_of_mult3 (+ step 1 ) (+ sum step))
)
)
我的想法是在步骤达到sum时结束递归,然后我将在我返回的sum变量中得到我需要的所有倍数,但是我的REPL似乎对这两个变量都返回nil,这里可能有什么错误 是一个表达式而不是语句。if
的结果始终是其中一个分支。事实上,Clojure并没有声明:
Clojure程序由表达式组成。编译器将未经特殊窗体或宏专门处理的每个窗体视为一个表达式,对其求值以生成一个值。没有声明或语句,尽管有时可能会对表达式的副作用进行评估,并忽略其值
有一本适合初学者的在线(免费)好书:
另外,Lisps中的括号并不等同于C族语言中的大括号。例如,我会将您的is_div_by_3
函数编写为:
(defn div-by-3? [number]
(zero? (mod number 3)))
对于sum\u of_mult3
函数,我还将使用更惯用的方法:
(defn sum-of-mult-3 [max]
(->> (range 1 (inc max))
(filter div-by-3?)
(apply +)))
我认为这段代码在意图上比递归版本更具表现力。唯一的技巧是线程的最后一个宏。查看线程最后一个宏的解释。此代码存在一些问题 1) 你的第一个
if
在sum\u mult3
中是一个noop。它返回的任何内容都不会影响函数的执行
2) 第二个if
在sum\u of_mult3
中只有一个条件,如果步长是3的倍数,则为直接递归。对于大多数数字,第一个分支将不被采用。第二个分支只是一个隐式的nil
。无论输入如何,函数都保证返回该参数(即使提供的第一个参数是三的倍数,下一个重复出现的值也不会返回)
3) 如果可能,使用recur
而不是self调用,self调用消耗堆栈,recur
编译成一个不消耗堆栈的简单循环
最后,一些风格问题:
1) 始终将关闭参数与其关闭的块放在同一行上。这使得Lisp风格的代码更具可读性,如果没有其他东西的话,我们大多数人也会阅读Algol风格的代码,把paren放在正确的位置会提醒我们正在阅读哪种语言
2) (如果(=0(型号3))真-假)
与(=0(型号3)
相同,后者又与(零)(型号3)相同)
3) 使用(inc x)
代替(+x 1)
4) 对于两个以上的潜在操作,请使用case
、cond
或condp
(defn sum-of-mult3
[step sum]
(cond (= step 100) sum
(zero? (mod step 3)) (recur (inc step) (+ sum step))
:else (recur (inc step) sum))
除了罗德里戈的答案之外,我想到的解决问题的第一个方法是:
(defn sum-of-mult3 [n]
(->> n
range
(take-nth 3)
(apply +)))
这应该是不言自明的。这里有一种不使用序列的更“数学”的方法,考虑到所有数字的总和(N*(N+1))/2(N*(N+1))
正如Rodrigo所说,递归不是完成这项任务的正确工具。作为一名学习者(不仅仅是回答你),仅仅迭代三的倍数不是更有效吗?e、 例如
(reduce+(take while#)(<%100)(iterate(partial+3)0))
。迂腐的观察:你不需要你的范围从1开始,而不是默认的0。@DiegoBasch我知道,我这样做是因为我认为它会更清晰。
(defn sum-of-mult3* [n]
(let [x (quot (dec n) 3)]
(* 3 x (inc x) 1/2)))