Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure: what's the difference between [D and [Ljava.lang.Double;?

Tags:

java

clojure

I'm trying to do some stuff with native Java arrays, and I'm not understanding what the difference is between the two double-array instantiations. Does this have to do with boxing and unboxing values? In all cases below the (first...) of every array has type java.lang.Double. Clojure protocols appear to be sensitive to the distinction.

user> (class (make-array Double/TYPE 3))  ;; [D
user> (class (double-array [1 2 3]))      ;; [D
user> (class (into-array (make-array Double/TYPE 3)))  ;; [Ljava.lang.Double;
user> (class (into-array (double-array [1 2 3])))      ;; [Ljava.lang.Double;
user> (class (into-array (repeat 2 (double-array [1 2 3]) ))) ;; [[D
like image 879
Sonicsmooth Avatar asked Dec 22 '13 07:12

Sonicsmooth


1 Answers

There are two different types of array to consider:

  • [D is a primitive double array, equivalent to Java double[]
  • [Ljava.lang.Double; is an array of Double references, equivalent to Java Double[].

(the odd notation is because this is the internal representation of these types in Java bytecode... it's a bit odd that this gets exposed in Clojure but you just have to live with it)

Because these are different types, they are treated differently with Clojure protocols.

The primitive double arrays usually offer better performance, assuming you stick to primitive double operations and avoid any unnecessary boxing. You can think of the primitive arrays as an array of unboxed values, and the reference arrays as an array of boxed values.

The main reason to use the reference arrays are if your values are already boxed when you receive them, and/or if you plan to pass them to other functions or collections that require boxed values. In this case, it is inefficient to unbox the doubles and then box them again, so it can be sensible to leave them in boxed form.

FWIW, there are several libraries that make it easy to do things with double arrays. In particular you should check out HipHip (specialised array operations), core.matrix (supports vector/matrix operations on many types including double arrays) and vectorz-clj (works with core.matrix, wraps double arrays as general purpose vectors)

like image 70
mikera Avatar answered Sep 28 '22 02:09

mikera