【问题标题】:Clojure : Integer cannot cast to IFnClojure:整数不能转换为 IFn
【发布时间】:2012-04-01 10:42:53
【问题描述】:

我得到了可怕的 * 不能在这里用一个简单的数学函数转换为 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) 排序错误的参数(显然 - 强制转换异常)。

我的问题很简单......如何修复这个 sn-p,并且可选地 - 我怎样才能一劳永逸地克服这个常见的异常?它似乎经常出现在我的 Clojure 编码探险中,我在想也许我还没有正确的开发风格。

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

更新:

我的代码中充满了不规则的语法。错误出现在内部函数中,其中 使用了 java/c 风格的函数调用:例如 max / log ...

【问题讨论】:

    标签: clojure


    【解决方案1】:

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

    Clojure 遵循标准的 lisp 约定,将不带引号的列表的第一个元素作为要调用的函数。换句话说,你想用 (log ...) 代替 log(...) 和 (max ...) 代替 (max (...))

    在您的特定风格中捕获这些错误非常容易:匹配“XXX(”的所有内容,其中 XXX 是任意数量的非空格、非括号字符都是错误的。

    【讨论】:

      【解决方案2】:

      在我看来,您的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 日志,请将 log 替换为 Math/log,这会调用 java.lang.Math 中的静态日志函数

      【讨论】:

      • 考虑将映射作为参数而不是一百万个有序参数传递,并使用 :keys 解构宏。
      【解决方案3】:

      调试这类事情得益于使用 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)))

      用户=>(损坏的 1) java.lang.ClassCastException:java.lang.Integer 不能转换为 clojure.lang.IFn (NO_SOURCE_FILE:0)

      user=>(使用 'clojure.stacktrace)

      user=>(打印堆栈跟踪(根本原因 *e)2) java.lang.ClassCastException:java.lang.Integer 不能转换为 clojure.lang.IFn 在 user$broken$internal__1206.invoke (NO_SOURCE_FILE:2) user$broken.invoke (NO_SOURCE_FILE:3)

      【讨论】:

        【解决方案4】:
        how can I defeat this common exception once and for all
        

        随着时间的推移和练习,dynamic typing 会变得更好。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-03-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-06-23
          • 1970-01-01
          相关资源
          最近更新 更多