这两个Clojure代码块有什么区别?

时间:2012-05-28 14:55:36

标签: loops clojure

在研究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块的值。

2 个答案:

答案 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的标签。