What are the best simple ways to speed up this function? The equivalent code in java is nearly 50 times faster according to Criterium.
I bet if I use a java Array and reduce the amount of boxing that would all help, but I thought I'd post first here to see if there was any basic mistakes I was making that could easily be fixed. Note I've already indicated (double...) for Clojure, which greatly improved the performance, but still nothing like Java. I've also first converted the seq using (double-array...) instead of using (vec ...) inside the function, and that also improved performance, but again, nothing like Java.
(defn cosine-similarity [ma mb]
(let [va (vec ma), vb (vec mb)]
(loop [p (double 0)
na (double 0)
nb (double 0)
i (dec (count va))]
(if (neg? i)
(/ p (* (Math/sqrt na) (Math/sqrt nb)))
(let [a (double (va i))
b (double (vb i))]
(recur (+ p (* a b))
(+ na (* a a))
(+ nb (* b b))
(dec i)))))))
Note that ma and mb are both seqs, containing 200 Doubles each. In the java version they are passed as double[] args.