如何在clojure中定义安全的sqrt函数?

时间:2014-05-16 17:39:10

标签: clojure genetic-programming

我正在使用fungp(遗传编程工具)来模拟复杂的函数并且遇到sqrt问题。

基本上,我必须将函数及其arity的向量传递给fungp,以便它可以组合它们的表达式。然后将评估表达式并返回最佳表达式。这个函数向量看起来像:

(def functions
  '[[+ 2]
  [- 2]
  [* 2]
  [fungp.util/abs 1]
  [fungp.util/sdiv 2]
  [fungp.util/sin 1]
  [fungp.util/sqrt 1]
  [inc 1]
  [dec 1]])

这个设置给了我一百行错误,如:

#<ClassCastException java.lang.ClassCastException: java.lang.Double cannot be cast to clojure.lang.IFn>

我认为这是由于fungp.util / sqrt的定义:

(defn sqrt [x] (if (x > 0) (Math/sqrt x) 0))

我认为0导致评估失败,但我不确定。我已经尝试定义我自己的安全平方根版本,但无法正确使用语法。

所以,这就是我被困的地方。我需要一个安全的平方根版本(负输入返回0)并在fungp表达式中正确评估。

编辑:为了完整性,这是我尝试编写自己的平方根包装器的(许多)变体之一:

(defn sqrt-fn [x] `(if (~x > 0) (Math/sqrt ~x) 0))

输出(中间位是从函数生成的表达式):

#<ClassCastException java.lang.ClassCastException: clojure.lang.Cons cannot be cast to java.lang.Number>

(let [] (- (dec (- (- (fungp.util/sin (tutorial.tut1/sqrt-fn 8.0)) (fungp.util/sdiv (* x 2.0) (dec 9.0))) (fungp.util/sdiv (tutorial.tut1/sqrt-fn (* x x)) (- (- x 4.0) (+ x x))))) (fungp.util/sdiv (tutorial.tut1/sqrt-fn (fungp.util/sin (
+ (dec x) (inc x)))) (fungp.util/sdiv (* (inc (inc 1.0)) (* (+ x 9.0) (fungp.util/sin 9.0))) (tutorial.tut1/sqrt-fn (- (tutorial.tut1/sqrt-fn x) (fungp.util/abs 3.0)))))))

NullPointerException   clojure.lang.Numbers.ops (Numbers.java:942)

我不是在写表达式,所以如果有额外的括号或缺少括号,它们就会来自我定义的sqrt。

1 个答案:

答案 0 :(得分:6)

这有几个问题:

(defn sqrt-fn [x] `(if (~x > 0) (Math/sqrt ~x) 0))

首先,正如评论中暗示的那样,(x > 0)试图将x(可能是一个数字)作为一个函数来调用。 >是函数,因此它必须首先出现,如(> x 0)

另外,你可能不希望它们在这里引用语法 - 这会阻止对内容的评估,因此你的函数会返回一个带引号的符号列表。