I'm trying to make a function in Clojure that is local to the body of a (let ...) function. I tried the following, but (defn ...) defines things in the global namespace.
(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))
Now, I also tried:
(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))
But then I get the error:
Exception in thread "main" java.lang.Exception: Unable to resolve symbol: power in this context (math.clj:6)
How do I make a function whose namespace is local to the let body and can recursively call itself?
For this you can use 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)))
Note that I also changed your nested if-construction to cond, I think it is more readable. Also I changed (+ exp 1) and (- exp 1) to (inc exp) and (dec exp) respectively. You can even improve your function more like using recur and an accumulator argument, but maybe that goes beyond the scope of your question. Also see Brian Carper's comment below.
letfn
is the best solution for your particular case. However, you can also created a named "anonymous" function like so:
(let [power (fn power [base exp] ...)]
(println (power -2 3)))
However, this style doesn't allow for mutually recursive functions, which letfn
does.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With