Clojure:整数不能转换为IFn

时间:2012-03-15 20:50:12

标签: clojure

我觉得可怕的 * 无法使用简单的数学函数转换为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 ...

4 个答案:

答案 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 Clojurehttp://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获得更好的效果。