I was lucky enough to be able to make it to San Francisco last week, not for you know what (who has two grand?), but to see coworkers and friends. It sure didn't hurt that JavaOne brought a lot of talent into the area, and I took advantage of that by attending Rich Hickey's talk at the special edition of the Bay Area Clojure User Group meetup. As Sean Corfield notes in the meetup feedback, the talk was both "entertaining and thought provoking," which I think is about all you can ask of a talk about language internals.
The big takeaway, I'd say, is that Rich is interested in making Clojure a language that runs code like the stuff we write run really damn fast. At the moment, he's working on static linking and enhanced primitive support, which looks like this:
(defn fib [n] (if (<= n 1) 1 (+ (fib (dec n)) (fib (- n 2))))) (time (fib 38)) "Elapsed time: 3565.579 msecs" ;; hint arg and return (defn ^:static fib ^long [^long n] (if (<= n 1) 1 (+ (fib (dec n)) (fib (- n 2))))) (time (fib 38)) "Elapsed time: 395.365 msecs"
That's right: add a few annotations to the method signature, and get
9x performance. Thanks to Clojure's autoboxing and promotion of
longs, this works for just about any values you'd want to use
There is one exception, and it was an important part of what Rich had
to say last Monday: this function, and most numeric functions in Clojure, will no
longer auto-promote values to
Big numbers to avoid overflowing
doubles. This is already somewhat
and will no
doubt remain so, but Rich did a good job of explaining its necessity
as a workaround for the JVM's inability to handle values that might be
objects or primitives. Inconveniencing legitimate consumers of
arbitrary precision math (you know who you are!) to make everyone else
happier is a tradeoff that makes sense to me.
The vision behind this work is the enablement of functional patterns with bare
metal performance -
mapping a statically linked function over an array
of primitives should be no slower than a corresponding imperative
loop. Performance of idiomatic code will be a feature of Clojure,
which is pretty uncommon.
Rich's presentation and the gaggle of smart people asking questions
yielded many other gems throughout the night. Clojure seems to be on
course for a solid amount of additional development. Parallelism will be
improved via fork/join and some cleanup of
binding semantics. Pods -
more on these after Clojure Conj - will
help bring side-effect laden Java code into the fold in a clean
way. Clojure's Java underpinnings will eventually move to Clojure,
and provide a much more solid foundation for tooling along with
them. These changes will largely be "additions" to the language or
entirely transparent, unlike some of the important changes to
semantics slated for the near future.
This, I think, is probably going to be the story of Clojure - the language - from here on out. Don't expect an actor model or an object system from the core implementation (add them if you really want them!). Do expect a healthy community of interesting, performant libraries and a language that will continue to take whatever steps are necessary to replace Java in your day to day life: this is the clear goal of its creator.