【问题标题】:How do I define a safe sqrt function in clojure?如何在 clojure 中定义安全的 sqrt 函数?
【发布时间】:2016-10-05 20:09:50
【问题描述】:

我正在使用 fungp(一种基因编程工具)来建模一个复杂的函数,并且遇到了 sqrt 的问题。

基本上,我必须将一个函数向量及其数量传递给 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 的方式。

【问题讨论】:

  • 我不认为这是从该错误中得出的正确结论。这只是意味着某些东西试图调用 0.0 就像它是一个函数一样。在 repl 中键入 (0.0) 会导致相同的异常。
  • @NathanHughes 所以,我很难掌握 clojure,我肯定是错的,但我认为这是问题的原因是,如果我从函数向量中省略平方根,一切正常(除了我的函数无法准确建模),如果我使用不安全的平方根包装器,ClassCastExceptions 就会消失,但由于负数,我会得到合同异常。
  • 我敢打赌,错误出在您的平方根包装器中。某处有一对额外的括号。请记住,括号在 clojure 中用于调用语义和列表文字,而不是评估分组的顺序。
  • @NathanHughes 感谢您的建议。我也觉得有额外的括号,但我不知道为什么/在哪里。我已经用关于我自己的包装器的更多信息更新了这个问题。
  • >_ x 0) (Math/sqrt x) 0)) -- 放弃你的中缀方式

标签: clojure genetic-programming


【解决方案1】:

这有几个问题:

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

首先,正如 cmets 中所暗示的,(x &gt; 0) 试图将x(可能是一个数字)作为函数调用。 &gt; 是函数,所以必须先出现,如(&gt; x 0)

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-14
    • 2016-05-12
    • 2010-10-15
    • 2016-01-04
    相关资源
    最近更新 更多