SICP sqrt NullPointerException

时间:2011-10-13 04:11:27

标签: clojure nullpointerexception sicp

我在Clojure中实现了一些开始的SICP代码时遇到了意外的NullPointerException。特别是,我想实现1.1.7节中的迭代平方根过程。

以下是代码:

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

这适用于足够小的值,例如(sqrt 16)。对于大于约NullPointerException clojure.lang.Numbers.lt (Numbers.java:3693)的任何输入,我收到(square 2718)错误。

有什么想法吗?

使用整个回溯进行更新(前一个是我在repl中获得的全部内容):

线程“main”java.lang.NullPointerException中的异常     在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)     在clojure.lang.Compiler.eval(Compiler.java:6465)     在clojure.lang.Compiler.load(Compiler.java:6902)     在clojure.lang.Compiler.loadFile(Compiler.java:6863)     在clojure.main $ load_script.invoke(main.clj:282)     在clojure.main $ script_opt.invoke(main.clj:342)     在clojure.main $ main.doInvoke(main.clj:426)     在clojure.lang.RestFn.invoke(RestFn.java:408)     在clojure.lang.Var.invoke(Var.java:401)     在clojure.lang.AFn.applyToHelper(AFn.java:161)     在clojure.lang.Var.applyTo(Var.java:518)     在clojure.main.main(main.java:37)

2 个答案:

答案 0 :(得分:1)

不确定这是否仍然相关,但我认为值得尝试使用LightTable Playground应用程序,让您了解事情是如何解释的:

light table demo screenshot of above code

您是否尝试使用最新版本,请说新的Clojure 1.4.0版本?

答案 1 :(得分:0)

嘿,它对我来说很好。我正在使用clojure 1.3.0。以下是终端输出。代码工作正常。

[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