Clojure:整数无法强制转换为IFn
我得到了可怕的*不能用简单的数学函数转换为IFn错误:Clojure:整数无法强制转换为IFn,clojure,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
(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编码探索中经常出现,我想也许我还没有找到正确的开发风格
--------------------------------------------------------------
更新:
我已经用不规则的语法把我的代码打了个谜。错误出现在内部函数中,这些函数
使用了java/c风格的函数调用:例如max/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中的静态日志函数。在我看来,有问题的表达式是(x32,(/m1 min_m1))和(x32,(/tca_ratio min_tca))以及日志(…)
Clojure遵循标准的lisp约定,将无引号列表的第一个元素作为要调用的函数。换句话说,您希望使用(log…)而不是log(…)和(max…)而不是(max(…)
在您的特定样式中捕获这些错误非常容易:所有与“XXX”(其中XXX是任意数量的非空格、非括号字符)匹配的内容都是错误
how can I defeat this common exception once and for all
随着时间和实践的推移,通过
动态键入
调试,您会变得更好。使用clojure.stacktrace或类似工具(clojure 1.3中可能有更好的/改进的选项,我还没有研究过),这类功能会从中受益,请参阅和
请注意,*e
绑定到repl的最新异常
例如:
user=>(定义已断开[x]
(让[内部(fn[y](y))]
(内部x)))
用户=>(断开的1)
java.lang.ClassCastException:无法将java.lang.Integer转换为
clojure.lang.IFn(无源文件:0)
user=>(使用“clojure.stacktrace”)
用户=>(打印堆栈跟踪(根本原因*e)2)
java.lang.ClassCastException:无法将java.lang.Integer转换为
clojure.lang.IFn
在用户$breaked$internal\uuuu 1206.invoke处(无源文件:2)
用户$breake.invoke(无源文件:3)
考虑将映射作为参数而不是一百万个有序参数传递,并使用:keys
解构宏。
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)