Primitive types support for fns coming to a Clojure branch near you

unsorted — cgrand, 10 June 2010 @ 8 h 57 min

Rich Hickey is working on primitive support in the prim branch. As of now, one can write:

(defn ^:static fib ^long [^long n]
  (if (>= (long 1) n)
    (long 1)
    (+ (fib (dec n)) (fib (- n (long 2))))))

and computes (fib 38) on my laptop in 650ms where my (or even Rich’s) best attempt took about 2s! If I tweak the above code to use unchecked ops (regular arithmetic ops on primitive types in Clojure throw an exception on overflow, unchecked ones don’t), the performance comes real real close (< 5%) to the equivalent Java code.

What’s this ^:static thing?

Primitive (double and long only: they subsume any other type) args and return values are only allowed on statics (note that the return type hint is put on the arglist so as to allow different hints for different arities). Statics are still fns in vars but they are backed by a static method and, when called by name, a direct static method call is emitted rather than going through the var and the IFn interface — as such static calls replace direct binding.

(my-static 42) ; direct call
(apply my-static 42 nil) ; regular call through the var

About the syntax: ^:keyword is a new reader shorthand for ^{:keyword true} (and keep in mind that in Clojure 1.2 ^ is the new #^), and metadata are merged: ^:static ^long ^{:doc "docstring"} x is now equivalent to ^{:static true :tag long :doc "docstring"} x.

Interesting times... as usual in the Clojure community. Thanks Rich!


  1. [...] up See here. Update: I was wrong and Rich Hickey set me right: I didn’t measure the gains I’m [...]

  2. This made my day. I’ve been writing some high performance code and this will be a huge help.

    Comment by DiG — 10 June 2010 @ 18 h 02 min
  3. I never thought primitive types are something to blog about. I guess it is like Apple blogging about cut-and-paste. Hopefully Clojure will take off in a big way for items like macros.

    Comment by fnprog — 11 June 2010 @ 0 h 22 min
  4. I am liking this performance changes, but I am wondering why are there two ^long hints. The [^long n] is for the return type hint, but what does the one after fib means?

    Comment by tonyl — 16 June 2010 @ 20 h 10 min
  5. @tonyl, the outer hint is for the return value.

    Comment by cgrand — 16 June 2010 @ 22 h 31 min

RSS feed for comments on this post. TrackBack URI

Leave a comment

(c) 2014 Clojure and me | powered by WordPress with Barecity