6

I've encountered an unexpected NullPointerException while implementing some beginning SICP code in Clojure. In particular, I want to implement the iterative square root procedure from section 1.1.7.

Here's the code:

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

This works fine for small enough values, e.g. (sqrt 16). I get a NullPointerException clojure.lang.Numbers.lt (Numbers.java:3693) error for any inputs larger than approximately (square 2718).

Any ideas?

Update with the whole traceback (the previous one is all I get in the repl):

Exception in thread "main" java.lang.NullPointerException at clojure.lang.Numbers.lt(Numbers.java:3693) at sicp_in_clojure.chapter_one$sqrt$good_enough_QMARK___14.invoke(chapter_one.clj:40) at sicp_in_clojure.chapter_one$sqrt.invoke(chapter_one.clj:43) at sicp_in_clojure.chapter_one$sqrt.invoke(chapter_one.clj:37) at sicp_in_clojure.chapter_one$eval19.invoke(chapter_one.clj:48) at clojure.lang.Compiler.eval(Compiler.java:6465) at clojure.lang.Compiler.load(Compiler.java:6902) at clojure.lang.Compiler.loadFile(Compiler.java:6863) at clojure.main$load_script.invoke(main.clj:282) at clojure.main$script_opt.invoke(main.clj:342) at clojure.main$main.doInvoke(main.clj:426) at clojure.lang.RestFn.invoke(RestFn.java:408) at clojure.lang.Var.invoke(Var.java:401) at clojure.lang.AFn.applyToHelper(AFn.java:161) at clojure.lang.Var.applyTo(Var.java:518) at clojure.main.main(main.java:37)

Alan O'Donnell
  • 1,276
  • 9
  • 17

2 Answers2

1

Not sure if this is still relevant or not, but I thought it worth trying it out using the LightTable Playground app that lets you see how things are interpreted:

light table demo screenshot of above code

Have you tried with a recent build, say the new Clojure 1.4.0 release?

Nick Klauer
  • 5,893
  • 5
  • 42
  • 68
0

Hey it worked fine for me. I Am using clojure 1.3.0. Following is the terminal output.The code works fine.

[user@myhost ~]$ 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
Sreenath Nannat
  • 1,949
  • 1
  • 13
  • 18
  • user=> (sqrt (square 5000)) gave me 5000.000000041231 – Sreenath Nannat Oct 14 '11 at 18:21
  • Fascinating :) The code above works perfectly on Clojure 1.2.1, but I keep getting these NullPointerExceptions with 1.3.0. Very odd. – Alan O'Donnell Oct 14 '11 at 20:59
  • My clojure version is 1.3.0 .You can see it in my response! I think it will be due to problem in your clojure installation. Make sure that you are not using the beta release(just incase if there is any bug in beta release) – Sreenath Nannat Oct 15 '11 at 10:22
  • By the way, this is my java installation, java version "1.6.0_22" OpenJDK Runtime Environment (IcedTea6 1.10.3) (ArchLinux-6.b22_1.10.3-1-x86_64) OpenJDK 64-Bit Server VM (build 19.0-b09, mixed mode) – Sreenath Nannat Oct 15 '11 at 10:27