2009-01-18 13 views
6

Tratar de hacer ejercicio 1.16 (versión iterativa de rápido-exp) en "Estructura e Interpretación de Programas Informáticos" con Clojure me ocurrió esto:Evaluación de parte 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))) 

Ponerlo a prueba:

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?! 

Parece que la parte "impar" de la expresión cond devuelve una función en lugar de evaluar. ¿Por qué? He intentado poner paréntesis alrededor de las expresiones después de los predicados, pero esa sintaxis parece ser incorrecta, esto es lo mejor que he podido encontrar. Estoy usando rev 1146 de Clojure.

+0

Si desea aplicar una función, entonces probablemente tiene que tener un paréntesis de apertura a la izquierda de sí mismo. Y en su última línea no hay '(' antes 'rápido-que-exp'. Y no solo en la última línea ... –

Respuesta

11

Prueba esto:

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

que no tengo REPL es conveniente, pero parece que lo que quiere.

+0

¿Qué demonios, pensé que había intentado todas las posibles permutaciones de paréntesis, pero parece que me perdí el derecho uno. Eso funcionó, muchas gracias Philip. :) –

+0

Ahum. ¿Por qué permutaciones de paréntesis? Si desea llamar a una función en Lisp, tiene que ser el primer elemento de una lista; así es como funciona la sintaxis Lisp. – Svante

+0

En Clojure, los paréntesis después del predicado son opcionales, como después del ejemplo anterior (= exp 0). Intenté sin, pero esa sintaxis era ambigua. Intenté con, pero puede haber tenido un paréntesis: más que era incorrecto. Pensé que había probado la versión de Philip también, pero debe haber hecho algo mal. –

6

Básicamente, lo que escribió podría volver a formatear como:

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

Así:

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, ya veo, eso explica el comportamiento original, gracias. También he logrado hacer los cálculos correctamente ahora, je. *sonrojo* –