在研究Clojure Koans时,我不得不迭代地计算一个数的阶乘,我确实找到了解决方案,但我对两个解决方案之间的区别提出了一个问题,一个有效,一个有效,尽管我不明白为什么:
有效的方法:
(defn factorial [n]
(loop [n n
acc 1]
(if (zero? n)
acc
(recur (dec n) (* n acc )))
)
那个没有的人:
(defn factorial [n]
(loop [n n
acc 1]
(if (zero? n)
1
(recur (dec n) (* n acc )))
)
请注意,唯一的区别是如果满足条件,则返回If块的值。
答案 0 :(得分:5)
第二个factorial
函数始终返回1
。代码构建为使用累加器变量(acc
),第一个代码块通过返回此累加器变量使其正确。
但是,如果未使用累加器变量,则可以编写factorial
函数来返回1
。由于此方法不使用loop
/ recur
,因此可能会导致堆栈溢出:尝试(fact 5000)
。
(defn factorial [x]
(if (<= x 1)
1
(* x (factorial (- x 1)))))
(source)
答案 1 :(得分:1)
很难弄清楚你认为应该发生的问题才有意义。
我想也许你认为loop
做得比它更多?你的代码几乎等同于:
(defn factorial
([n] (factorial n 1)
([n acc]
(if (zero? n)
acc
(recur (dec n) (* n acc)))))
是
的堆栈安全版本(defn factorial
([n] (factorial n 1)
([n acc]
(if (zero? n)
acc
(factorial (dec n) (* n acc)))))
所以acc
(或1
)是函数返回的最终值。
loop
所做的就是为recur
提供不同的目标,如果您在函数的开头和要重复的点之间有一些代码,这将非常有用。它基本上是goto的标签。