2012-03-15 71 views
6

即时得到可怕的*不能转换到IFN错误用一个简单的数学函数在这里:的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))))) 

;;;;;;;;;;;;

的ARG游戏只是一串数字:

(calc 1 2 3 4 5 1 2 3 4 5 1) 

我的想法/我的问题

通常,当我得到这个错误,我发现这是由于

1 )一个额外的括号(即,当我意外地在我的代码中加入额外的封闭)或

2)错误排列的参数(显然 - 演员例外)。

我的问题是简单的...如何解决这个片段,以及可选的 - 我怎么能一劳永逸地打败这个常见的异常?看来它在我的Clojure编码考察中经常发生,我想也许我还没有得到正确的开发风格。

--------------------------------------------- ----------

UPDATE:

我已经千疮百孔我的代码以unregular语法。这个错误发生在内部函数中,其中 使用了一个java/c风格函数调用:例如max/log ...

回答

6

它在我看来像你有一个log(sc1)等调用的问题。

应然看(假设日志某处定义)是这样的:

(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日志,用Math/log取代log这java.lang.Math中调用静态日志功能

+0

考虑通过一个地图作为参数,而不是一百万有序的参数和使用':keys'解构宏。 – 2014-04-12 14:45:56

14

在我看来像有害的表达式是(x32,(/ m1 min_m1))和(x32,(/ tca_ratio min_tca))以及log(..)ones。

Clojure遵循标准的lisp约定,即将不带引号的列表的第一个元素作为调用函数。换句话说,您希望(log ...)而不是(log)(...)和(max ...)而不是(max(...))

捕获这些错误非常简单您的特定风格:一切符合“XXX(” XXX是任意数量的非空间,非括号字符是一个错误

0
how can I defeat this common exception once and for all 

随着时间的推移和实践,你会得到与dynamic typing更好

1

使用clojure.stacktrace或类似工具(在Clojure 1.3中可能有更好的/改进的选项,我还没有研究过)来调试这种东西,请参见Obtain a callstack in Clojure d 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)