【问题标题】:What is the difference between these two blocks of Clojure code?这两个 Clojure 代码块有什么区别?
【发布时间】:2012-05-28 14:55:35
【问题描述】:

在处理 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 块的返回值。

【问题讨论】:

    标签: loops clojure


    【解决方案1】:

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

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

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

    (source)

    【讨论】:

    • 感谢您为我解决这个问题 :) 我知道递归解决方案及其局限性,但感谢您的提醒。
    【解决方案2】:

    很难弄清楚您认为应该发生什么才能使问题有意义。 我想也许你认为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 的标签。

    【讨论】:

      猜你喜欢
      • 2012-01-30
      • 1970-01-01
      • 1970-01-01
      • 2018-01-14
      • 2011-12-24
      • 2021-01-06
      • 2020-03-29
      相关资源
      最近更新 更多