我觉得可怕的 * 无法使用简单的数学函数转换为IFn错误:
(defn calc [sc1 m1 alpha beta gamma ta1 tb1 min_m1 min_tca tca_ratio x32]
(*
(max(0,
(+
(* alpha log(sc1))
(* beta log(m1))
(* gamma (/ ta1 tb1))
(- log(ta1) log(tb1)))))
(max(x32,(/ m1 min_m1)))
(max(x32,(/ tca_ratio min_tca)))))
;;;;;;;;;;;;
args只是一堆数字:
(calc 1 2 3 4 5 1 2 3 4 5 1)
我的想法/我的问题
通常,当我收到此错误时,我发现它是由于
1)一个额外的括号(即当我不小心在我的代码中添加一个额外的闭包)或
2)错误的参数(显然是一个演员例外)。
我的问题很简单......如何修复此片段,以及可选 - 如何一劳永逸地打败这个常见异常?它似乎经常在我的Clojure编码探险中出现,我想也许我还没有得到正确的开发风格。
-------------------------------------------- -----------
更新:
我用不规则的语法填充了我的代码。错误发生在内部函数中 使用了java / c样式函数调用:例如max / log ...
答案 0 :(得分:14)
在我看来,有问题的表达式是(x32,(/ m1 min_m1))和(x32,(/ tca_ratio min_tca))以及日志(..)。
Clojure遵循标准的lisp约定,即将不带引号列表的第一个元素作为调用函数。换句话说,你想要(log ...)代替log(...)和(max ...)而不是(max(...))
以您的特定风格捕获这些错误非常简单:匹配“XXX”的所有内容,其中XXX是任意数量的非空格,非括号字符是错误。
答案 1 :(得分:6)
我认为您对log(sc1)
等电话有疑问。
应该看(假设log在某处定义)类似于:
(defn calc [sc1 m1 alpha beta gamma ta1 tb1 min_m1 min_tca tca_ratio x32]
(*
(max 0
(+
(* alpha (log sc1))
(* beta (log m1))
(* gamma (/ ta1 tb1))
(- (log ta1) (log tb1))))
(max x32 (/ m1 min_m1))
(max x32 (/ tca_ratio min_tca))))
如果您只想使用Java日志,请将log
替换为调用java.lang.Math中的静态日志函数的Math/log
答案 2 :(得分:1)
使用clojure.stacktrace或类似的东西(在Clojure 1.3中我可能没有研究过更好/改进的选项)调试此类事情会有所帮助,请参阅Obtain a callstack in Clojure和http://tech.puredanger.com/2010/02/17/clojure-stack-trace-repl/。
请注意,*e
绑定到repl上的最新异常。
例如:
user=> (defn broken [x]
(let [internal (fn [y] (y))]
(internal x)))
user=> (broken 1)
java.lang.ClassCastException: java.lang.Integer cannot be cast to
clojure.lang.IFn (NO_SOURCE_FILE:0)
user=> (use 'clojure.stacktrace)
user=> (print-stack-trace (root-cause *e) 2)
java.lang.ClassCastException: java.lang.Integer cannot be cast to
clojure.lang.IFn
at user$broken$internal__1206.invoke (NO_SOURCE_FILE:2)
user$broken.invoke (NO_SOURCE_FILE:3)
答案 3 :(得分:0)
how can I defeat this common exception once and for all
通过时间和练习,您可以通过dynamic typing
获得更好的效果。