如何使let体的局部递归函数

dbm*_*kus 4 recursion clojure

我正在尝试在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))
Run Code Online (Sandbox Code Playgroud)

现在,我也尝试过:

(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))
Run Code Online (Sandbox Code Playgroud)

但后来我得到了错误:

Exception in thread "main" java.lang.Exception: Unable to resolve symbol: power in this         context (math.clj:6)
Run Code Online (Sandbox Code Playgroud)

如何创建一个函数,其命名空间是let body的本地,并且可以递归调用自身?

Mic*_*ent 10

为此您可以使用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)))
Run Code Online (Sandbox Code Playgroud)

请注意,我还将嵌套的if-construction更改为cond,我认为它更具可读性.我也分别将(+ exp 1)和( - exp 1)改为(inc exp)和(dec exp).您甚至可以使用recur和accumulator参数来改进函数,但这可能超出了您的问题的范围.另见Brian Carper的评论如下.