2

在处理 Clojure Koans 时,我不得不迭代地计算一个数字的阶乘,我确实找到了解决方案,但我对 2 个解决方案之间的区别有疑问,一个有效,一个无效,虽然我没有不明白为什么:

一个有效的:

(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 块的返回值。

4

2 回答 2

5

第二个factorial函数总是返回1。该代码使用累加器变量 ( acc) 构建,第一个代码块通过返回此累加器变量来正确处理它。

但是,如果不使用累加器变量,则factorial可以编写一个函数来返回。1由于此方法没有使用loop/ recur,因此很容易导致堆栈溢出: try (fact 5000)

(defn factorial [x]
  (if (<= x 1)
      1
      (* x (factorial (- x 1)))))

来源

于 2012-05-28T15:02:20.800 回答
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(or 1) 是函数返回的最终值。

所做loop的只是为 提供不同的目标recur,如果您在函数的开头和要重复的点之间有一些代码,这很有用。它基本上是一个 goto 的标签。

于 2012-05-28T16:54:33.027 回答