Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Evaluation of part of Clojure cond

Trying to do exercise 1.16 (iterative version of fast-exp) in "Structure and Interpretation of Computer Programs" with Clojure I came up with this:

(defn fast-it-exp [base exp res]
  (cond (= exp 0) res
  (odd? exp) fast-it-exp base (- exp 1) (* base res)
  :else fast-it-exp base (/ exp 2) (* base base res)))

Trying it out:

user=> (fast-it-exp 0 0 10)
10   ;yep
user=> (fast-it-exp 2 2 2)
1     ;no...
user=> (fast-it-exp 1 1 1)
#<user$fast_it_exp__59 user$fast_it_exp__59@138c63>    ;huh?!

Seems the "odd" part of the cond expression returns a function instead of evaluating. Why? I've tried putting parenthesis around the expressions after the predicates but that seems to be incorrect syntax, this is the best I've been able to come up with. I'm using rev 1146 of Clojure.

like image 416
Lars Westergren Avatar asked Jan 18 '09 14:01

Lars Westergren


2 Answers

Try this:

 (defn fast-it-exp [base exp res]
  (cond (= exp 0) res
        (odd? exp) (fast-it-exp base (- exp 1) (* base res))
        :else (fast-it-exp base (/ exp 2) (* base base res))))

I have no REPL handy but is looks like what you want.

like image 130
Phil Calçado Avatar answered Nov 15 '22 04:11

Phil Calçado


Basically, what you wrote could be reformatted as:

(defn fast-it-exp [base exp res]
  (cond
    (= exp 0) res
    (odd? exp) fast-it-exp
    base (- exp 1)
    (* base res) :else
    fast-it-exp base
    (/ exp 2) (* base base res)))

So:

user=> (fast-it-exp 0 0 10) ; (= exp 0) => res
10   ;yep
user=> (fast-it-exp 2 2 2)  ; base => (- exp 1)
1     ;no...
user=> (fast-it-exp 1 1 1)  ; (odd? exp) => fast-it-exp
#<user$fast_it_exp__59 user$fast_it_exp__59@138c63>    ;huh?!
like image 6
Chris Turner Avatar answered Nov 15 '22 04:11

Chris Turner