我正在尝试在 Clojure 中创建一个位于 (let ...) 函数主体的本地函数。我尝试了以下操作,但是 (defn ...) 在全局命名空间中定义了事物。
(let [] (defn power [base exp]
(if (= exp 0)
1
(if (> exp 0)
; Exponent greater than 0
(* base (power base (- exp 1)))
; Exponent less than 0
(/ (power base (+ exp 1)) base))))
(println (power -2 3)))
; Function call outside of let body
(println (power -2 3))
现在,我也尝试过:
(let [power (fn [base exp]
(if (= exp 0)
1
(if (> exp 0)
; Exponent greater than 0
(* base (power base (- exp 1)))
; Exponent less than 0
(/ (power base (+ exp 1)) base))))]
(println (power -2 3)))
; Function call outside of let body
(println (power -2 3))
但随后我收到错误:
Exception in thread "main" java.lang.Exception: Unable to resolve symbol: power in this context (math.clj:6)
如何创建一个命名空间位于 let 主体本地并且可以递归调用自身的函数?
最佳答案
为此,您可以使用letfn
:
(letfn [(power [base exp]
(cond
(= exp 0)
1
(> exp 0) ; Exponent greater than 0
(* base (power base (dec exp)))
:else ; Exponent less than 0
(/ (power base (inc exp)) base)))]
(print (power -2 3)))
请注意,我还将您的嵌套 if 结构更改为 cond,我认为它更具可读性。另外,我将 (+ exp 1) 和 (- exp 1) 分别更改为 (inc exp) 和 (dec exp)。您甚至可以更像使用 recur 和累加器参数来改进您的函数,但这可能超出了您的问题的范围。另请参阅下面 Brian Carper 的评论。
关于recursion - 如何使递归函数成为 let 主体的本地函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4119293/