Joseph Yourine
Joseph Yourine

Reputation: 1331

Clojure : type hint tower

I write sometimes java methods, especially for primitives/arrays operations and I am always stuck about how to use type hints under Clojure 1.8. I saw some threads but they are (maybe ?) outdated considering they have been posted more than 2 years ago.

I will give a basic example to illustre my point (I know this example is a bit pointless). Here i want to sum two double and to return a double.

Here is a Java method :

public static double add (double a, double b) {

    return a + b;
}

Then I would like to have a Clojure wrapper :

Version 1

(defn d+ ^double 
  [^double a ^double b]
  (Doubles/add a b))

Version 2

(defn d+ ^double 
  [^double a ^double b]
  (Doubles/add ^double a ^double b))

Version 3

(defn d+ ^double 
  [^double a ^double b]
  (Doubles/add (double a) (double b)))

I do not know where to put type hints and how to put them. I have the impression that (double x) is less efficient since it is a function (maybe I am wrong ?). Then what is the difference between giving hints inside body function or outside ?

Or maybe these hints are not necessary since there is only one method in the Java class ? I do not see the logic so generally I use version 1 or 3 (more is better ?).

Note that for this example, Clojure + is always faster

Upvotes: 2

Views: 365

Answers (1)

ClojureMostly
ClojureMostly

Reputation: 4713

Version 1 is correct. It'll emit the following byte code:

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);
    }
}

Where Primitives.add is just like your Doubles/add function.

If you want performance and avoid boxing you should set:

(set! *unchecked-math* :warn-on-boxed)

Also going through the Java interop reference (CTRL+F "primitive") will help.

Upvotes: 3

Related Questions