Clojure : 类型提示塔
Posted
技术标签:
【中文标题】Clojure : 类型提示塔【英文标题】:Clojure : type hint tower 【发布时间】:2017-07-27 16:07:56 【问题描述】:我有时会编写 java 方法,特别是对于基元/数组操作,我总是纠结于如何在 Clojure 1.8 下使用类型提示。我看到了一些线程,但考虑到它们已在 2 年多前发布,它们(也许?)已经过时了。
我将举一个基本的例子来说明我的观点(我知道这个例子有点毫无意义)。在这里,我想将两个 double
相加并返回一个 double
。
这是一个Java方法:
public static double add (double a, double b)
return a + b;
然后我想要一个 Clojure 包装器:
版本 1
(defn d+ ^double
[^double a ^double b]
(Doubles/add a b))
第 2 版
(defn d+ ^double
[^double a ^double b]
(Doubles/add ^double a ^double b))
第 3 版
(defn d+ ^double
[^double a ^double b]
(Doubles/add (double a) (double b)))
我不知道在哪里放置类型提示以及如何放置它们。我的印象是(double x)
效率较低,因为它是一个函数(也许我错了?)。
那么在 body 函数内部和外部给出提示有什么区别呢?
或者也许这些提示是不必要的,因为 Java 类中只有一种方法? 我看不到逻辑,所以我通常使用版本 1 或 3(越多越好?)。
请注意,对于此示例,Clojure + 总是更快
【问题讨论】:
*warn-on-reflection*
标志将有助于这种探索。只需将其设置为 true,编译器就会发出无法选择所需方法重载并需要提示的情况。
谢谢我已经测试过了,最后不需要任何提示。你知道为什么这个函数比较慢,因为它只适用于 double 吗?我的直觉是互操作意味着一些隐藏的操作/成本,因此 Java 互操作只有在函数成本高(如大算法)或函数在 Clojure 中不存在时才值得。
@leetwinski 原始类型提示与反射警告无关,它们是针对对象的。原始提示用于避免装箱的性能。更好的是在你的 clojure 文件请求时启用(set! *unchecked-math* :warn-on-boxed)
。
【参考方案1】:
版本 1 是正确的。它将发出以下字节码:
public final class compile_inspect$d_PLUS_ extends AFunction implements DDD
public compile_inspect$d_PLUS_()
public static double invokeStatic(double a, double var2)
return Primitives.add(a, var2);
public Object invoke(Object var1, Object var2)
return new Double(invokeStatic(RT.uncheckedDoubleCast((Number)var1), RT.uncheckedDoubleCast((Number)var2)));
public final double invokePrim(double var1, double var3)
return invokeStatic(var1, var3);
Primitives.add
就像您的 Doubles/add
函数一样。
如果您想要性能并避免拳击,您应该设置:
(set! *unchecked-math* :warn-on-boxed)
同时通过Java interop reference(CTRL+F“原始”)也会有所帮助。
【讨论】:
非常感谢,我也有关于附属问题的答案 ==> “并且数字基元将变成数字,除非它们立即被采用基元的方法使用。”这解释了简单操作的孤立性能有点差,还有一些不可能的任务(使用返回 double/float/etc 的方法扩展接口)以上是关于Clojure : 类型提示塔的主要内容,如果未能解决你的问题,请参考以下文章