Clojure:类型提示塔

Clojure : type hint tower

我有时会编写 java 方法,尤其是 primitives/arrays 操作,而且我总是对如何在 Clojure 1.8 下使用类型提示感到困惑。我看到了一些主题,但考虑到它们已经发布超过 2 年,它们已经(也许?)过时了。

我将举一个基本的例子来说明我的观点(我知道这个例子有点毫无意义)。在这里我想总结两个 double 和 return 一个 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 class 中只有一种方法? 我看不到逻辑,所以通常我使用版本 1 或 3(越多越好?)。

请注意,对于此示例,Clojure + 总是更快

版本 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 "primitive") 也会有所帮助。