2009-01-18 8 views
6

Essayer de faire de l'exercice 1,16 (version itérative de-exp rapide) dans « Structure et interprétation des programmes informatiques » avec Clojure je suis venu avec ceci:évaluation d'une partie de Clojure cond

(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))) 

l'essayer:

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 [email protected]> ;huh?! 

Semble que la partie "impaire" de l'expression cond renvoie une fonction au lieu de l'évaluer. Pourquoi? J'ai essayé de mettre des parenthèses autour des expressions après les prédicats mais cela semble être une syntaxe incorrecte, c'est le meilleur que j'ai pu trouver. J'utilise la version 1146 de Clojure.

+0

Si vous souhaitez appliquer une fonction, il a obtenu sans doute d'avoir une parenthèse d'ouverture à gauche lui-même. Et dans votre dernière ligne il n'y a pas de '(' avant 'fast-it-exp'.) Et pas seulement dans la dernière ligne ... –

Répondre

11

Essayez ceci:

(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)))) 

Je n'ai pas REPL à portée de main, mais est ressemble à ce que vous voulez.

+0

Que diable, je pensais avoir essayé toutes les permutations possibles de parenthèses, mais il semble que j'ai raté le bon Un qui a fonctionné, merci beaucoup Philip. :) –

+0

Ahum. Pourquoi les permutations de parenthèses? Si vous voulez appeler une fonction en Lisp, cela doit être le premier élément d'une liste; C'est ainsi que fonctionne la syntaxe Lisp. – Svante

+0

Dans les parenthèses Clojure après le prédicat sont facultatifs, comme après l'exemple (= exp 0) ci-dessus. Essayé sans, mais cette syntaxe était ambigu. Essayé avec, mais j'ai peut-être eu une parenthèse autour: autre qui était incorrect. Je pensais avoir essayé la version de Philip aussi, mais j'ai dû faire quelque chose de mal. –

6

Fondamentalement, ce que vous avez écrit pourrait être reformaté comme:

(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))) 

Alors:

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 [email protected]> ;huh?! 
+0

Ah, je vois, cela explique le comportement original, merci. J'ai aussi réussi à faire les calculs correctement maintenant, heh. *rougir* –