Clojure无法调用Smile 3.0.0中MathEx类的特定方法
问题:升级Smile至3.0.0后部分Java方法无法在Clojure中调用
将Smile包升级至3.0.0后,部分方法无法在Clojure中调用。Leiningen项目的project.clj中依赖配置为:
[com.github.haifengl/smile-core "3.0.0"]
在REPL中执行代码时出现如下情况:
(import smile.math.MathEx) (MathEx/log2 5.) => 2.321928094887362 (MathEx/pow2 5.) Syntax error (IllegalArgumentException) compiling . at (C:\Users\AAlmosni\AppData\Local\Temp\1\form-init13649993705313983821.clj:1:1). No matching method pow2 found taking 1 args for class smile.math.MathEx (MathEx/sigmoid 5.) Syntax error (IllegalArgumentException) compiling . at (C:\Users\AAlmosni\AppData\Local\Temp\1\form-init13649993705313983821.clj:1:1). No matching method sigmoid found taking 1 args for class smile.math.MathEx (MathEx/isPower2 32) => true
这种部分方法可用、部分不可用的情况令人困惑。以下是MathEx.class的关键代码片段:
public static double log2(double x) { return Math.log(x) / LOG2; } public static double log(double x) { double y = -690.7755D; if (x > 1.0E-300D) { y = Math.log(x); } return y; } public static double log1pe(double x) { double y = x; if (x <= 15.0D) { y = Math.log1p(Math.exp(x)); } return y; } public static boolean isInt(float x) { return x == (float)Math.floor((double)x) && !Float.isInfinite(x); } public static boolean isInt(double x) { return x == Math.floor(x) && !Double.isInfinite(x); } public static boolean equals(double a, double b) { if (a == b) { return true; } else { double absa = Math.abs(a); double absb = Math.abs(b); return Math.abs(a - b) <= Math.min(absa, absb) * 2.220446049250313E-16D; } } public static double sigmoid(double x) { x = Math.max(-36.0D, Math.min(x, 36.0D)); return 1.0D / (1.0D + Math.exp(-x)); } public static double pow2(double x) { return x * x; } public static boolean isPower2(int x) { return x > 0 && (x & x - 1) == 0; }
原因分析与解决方法
原因
问题根源在于Clojure的Java方法解析机制,以及Smile 3.0.0中MathEx类的方法重载冲突:
- Clojure调用Java静态方法时,会严格根据传入参数的类型匹配方法签名。如果存在同名但参数类型不同的重载方法,且Clojure无法明确推断出目标方法,就会抛出"找不到匹配方法"的错误。
- 你提供的代码片段之外,
pow2和sigmoid大概率存在其他重载版本(比如接受float类型参数的版本),而Clojure中5.是Double类型,导致重载匹配时出现歧义。 - 而
log2和isPower2能正常调用,是因为它们没有重载版本,或者重载版本的参数类型差异足够明显,Clojure可以准确匹配。
解决方法
- 显式指定参数类型:通过类型提示告诉Clojure要匹配的方法签名,示例如下:
; 方式一:强制转换参数类型 (MathEx/pow2 (double 5.)) (MathEx/sigmoid (double 5.)) ; 方式二:使用类型注解 (MathEx/pow2 ^double 5.) (MathEx/sigmoid ^double 5.)
- 查阅Smile官方文档,确认
pow2和sigmoid的所有重载版本,确保调用时参数类型与目标方法完全匹配。
内容的提问来源于stack exchange,提问作者alex314159
相关产品推荐
相关产品推荐

