2011-10-13 16 views
6

He encontrado una inesperada excepción NullPointerException al implementar algún código SICP inicial en Clojure. En particular, quiero implementar el procedimiento iterativo de raíz cuadrada de la sección 1.1.7.SICP sqrt NullPointerException

Aquí está el código:

(defn square [x] (* x x)) 

(defn abs [x] 
    (cond 
    (< x 0) (- x) 
    :else x)) 

(defn average [x y] 
    (/ (+ x y) 2)) 

(defn sqrt 
    ([x] (sqrt 1.0 x)) 
    ([guess x] 
    (letfn [(good-enough? [guess] 
       (< (abs (- (square guess) x)) 0.001)) 
      (improve [guess] 
       (average guess (/ x guess)))] 
     (if (good-enough? guess) 
     guess 
     (recur (improve guess) x))))) 

Esto funciona bien para valores suficientemente pequeños, por ejemplo, (sqrt 16). Obtengo un error NullPointerException clojure.lang.Numbers.lt (Numbers.java:3693) para cualquier entrada mayor que aproximadamente (square 2718).

¿Alguna idea?

actualización con todo el rastreo (el anterior es todo lo que consigo en el sust):

Excepción en el hilo "principal" java.lang.NullPointerException en clojure.lang.Numbers.lt (Numbers.java : 3693) en sicp_in_clojure.chapter_one $ sqrt $ good_enough_QMARK ___ 14.invoke (chapter_one.clj: 40) en sicp_in_clojure.chapter_one $ sqrt.invoke (chapter_one.clj: 43) en sicp_in_clojure.chapter_one $ sqrt.invoke (chapter_one.clj : 37) en sicp_in_clojure.chapter_one $ eval19.invoke (chapter_one.clj: 48) en clojure.lang.Compiler.eval (Compiler.java:6465) en clojure.lang.C ompiler.load (Compiler.java:6902) en clojure.lang.Compiler.loadFile (Compiler.java:6863) en clojure.main $ load_script.invoke (main.clj: 282) en clojure.main $ script_opt. invoke (main.clj: 342) en clojure.main $ main.doInvoke (main.clj: 426) en clojure.lang.RestFn.invoke (RestFn.java:408) en clojure.lang.Var.invoke (Var.java:401) en clojure.lang.AFn.applyToHelper (AFn.java:161) en clojure.lang.Var.applyTo (Var.java:518) en clojure.main.main (main.java: 37)

+0

¿Se puede pegar todo el rastreo? – poolie

+0

No puedo reproducir el error, funciona bien para mí, incluso para números más grandes. ¿Con qué versiones de Clojure/Java trabajas? –

+0

Tampoco puedo reproducir - Supuse que sus funciones cuadradas son (defn cuadrado [x] (* x x)). Copiar y pegar el código de lo contrario. – Paul

Respuesta

0

Hola, funcionó bien para mí. Estoy usando clojure 1.3.0. Lo siguiente es la salida del terminal. El código funciona bien.

[[email protected] ~]$ clj 
Clojure 1.3.0 
user=> (defn square [x] (* x x)) 
#'user/square 
(defn abs [x] 
    (cond 
    (< x 0) (- x) 
    :else x)) 
#'user/abs 
(defn average [x y] 
    (/ (+ x y) 2)) 
#'user/average 
(defn sqrt 
    ([x] (sqrt 1.0 x)) 
    ([guess x] 
    (letfn [(good-enough? [guess] 
       (< (abs (- (square guess) x)) 0.001)) 
      (improve [guess] 
       (average guess (/ x guess)))] 
     (if (good-enough? guess) 
     guess 
     (recur (improve guess) x))))) 
#'user/sqrt 
user=> (sqrt 16) 
4.000000636692939 
user=> (sqrt 2718) 
52.134441897781194 
user=> (sqrt 3000) 
54.77225658092904 
+1

¿Puedes probar tu código para (sqrt (square 3000))? –

+0

usuario => (sqrt (cuadrado 5000)) me dio 5000.000000041231 –

+0

Fascinante :) El código anterior funciona perfectamente en Clojure 1.2.1, pero sigo obteniendo estas NullPointerExceptions con 1.3.0. Muy raro. –

1

No estoy seguro si esto sigue siendo relevante o no, pero pensé que vale la pena probar a cabo mediante la aplicación LightTable Playground que le permite ver cómo se interpretan las cosas:

light table demo screenshot of above code

Ha intentado con una compilación reciente, digamos la nueva versión Clojure 1.4.0?

Cuestiones relacionadas