Rich Hickey, inventor of the Clojure language, and Stuart Halloway, author of “Programming Clojure,” presented introductory and advanced concepts of the young JVM language at Wednesday’s Northern Virginia Java Users Group. These are some of my notes from the meeting. The session served to whet interest in learning Clojure, thus these notes do not include a lot of code or explain Clojure’s unusual syntax. There are many other sources for that.
Clojure, a Lisp-like language that compiles to Java byte code and runs on the Java virtual machine, was created as a general-purpose programming language that embraces a functional style of software design, rather than the imperative style typical in languages like Java — and most other general purpose languages in use today. Functional programming languages like Clojure, Scheme and Erlang have been getting a lot of attention at technology conferences over the last few years, which first brought my attention to Clojure. Its functional style and its ability to run alongside and integrate with existing Java code interested me in learning more about Clojure. The fact that its inventor and a technology instructor I highly respect were presenting a free session on Clojure compelled me to attend the JUG meeting.
Rich Hickey released the first version of Clojure in October, 2007, with version 1.0 released May 1, 2009. We are talking about a young language. Still, from what I learned last night, it looks like a powerful language with potential. Clojure is released as open source under the Eclipse Public License 1.0, which makes it easy to use in a non-open source commercial environment.
Stu Halloway, co-founder of the top-notch professional training and agile consulting company Relevance Inc., began with an introduction to Clojure’s features and why a Java developer might want to learn it. Rich then took over and introduced three new features of Clojure (Protocols, Reify and Datatypes) that can be downloaded from the latest source tree but are not part of the current 1.1 release of the language.
According to Stu, some of the compelling features of Clojure are its:
- Easy interoperability with Java
- Lisp syntax
- Functional style
- Ability to run in a multi-threaded environment with no coding overhead
To demonstrate the syntax benefit, Stu “refactored” the StringUtils.isBlank method from the Apache Commons lang library. He started by showing the full Java source code and then removing all the ceremonial scaffolding code to expose the core logic, then simplified the Java code into the definition of an equivalent Clojure function:
(defn blank? [s] (every? #(Character/isWhitespace %) s))
I’m not a Clojure programmer (yet) but I think I captured the above syntax correctly. Like Ruby, Clojure uses the question mark to replace the traditional “is” prefix in boolean functions. The # symbol introduces an anonymous function. From what Stu described, the functional programming paradigm in Clojure handles most (all?) corner cases for you. There is no need to write special-case “if” statements to deal with a null parameter, for instance.
For Clojure’s interoperability with Java, Clojure code can call Java, and Java code can call Clojure functions. (According to Rich, the integration is implemented with little or no need to use Java reflection at runtime, adding less runtime overhead.)
For Clojure’s advantage by using Lisp syntax, Stu referred everyone to Paul Graham’s 2001 article, “What Made Lisp Different” as the best explanation. Most languages have “special forms” like imports, scopes, protection definitions, metadata, keywords. These special forms are language features you can use, but you cannot create them yourself and add them to the language. These language features are thus unavailable for reuse. Lisp abandoned this restriction. In a Lisp-like language, special forms of the language look like anything else in the language. All forms of the language are created equal. In Lisp (and Clojure), defining scope, the control flow, method calls, operators, functions, import mechanisms — they are all lists. Stu said a language’s “special forms” restrictions cause a programming language to “crap out,” and joked that the restrictions bring about magical cut-and-paste reuse workarounds we call “design patterns.”
For Clojure’s advantage by being a functional language, Clojure encourages you to write small pieces of code that work well together. Good code has the same shape as pseudo code, he said, and Clojure’s functional style lets you create more pseudo-code looking real code. According to Stu, functional languages are simpler to understand. They let you write code that eliminates or reduces what he called “incidental complexity” required by non-functional languages:
- Corner cases
- Class definitions
- Internal exit points
The resulting code is less complex, he said, and simpler to understand by orders of magnitude.
The final benefit he talked about is Clojure’s inherent ability to run in a multi-threaded environment with no special concurrency-handling code from the developer. Clojure and other functional programming languages perform this feat by treating data as immutable and producing a new copy of a data structure when data needs to be changed. Two threads never look at the same data at the same time, so there is never any need to synchronize access to code that reads and writes data. Clojure’s solution, Stu said, is to separate identify from value. He went on to explain what this means, but maybe the late hour caused me to miss the details.
After Stuart set the stage for why learn and use Clojure, Rich Hickey took over to talk about new features he is adding to the language. He said, quite truthfully, that for those in the audience who don’t already know Clojure, what he was about to say would not make a lot of sense. These features are Protocols, Reify and Datatypes. As a result of my newness to Clojure, I will pass along what I thought Rich said and hope he and the Clojure crowd forgive my ignorance.
Rich, for an open source programming language inventor, was a refreshingly clear advocate for his new language. Maybe I’m jaded from years of slogging through open-source code, but from my experience, most open source projects release their code with little explanation of how or even why to use it, and then treat users like they are the ones who failed if they misunderstand how to use the code correctly. Rich actually understood where most of us in the audience were coming from. “I know it’s a big deal to try to learn a new programming language,” he said, but he believes Clojure is worth taking the time to learn and will make our jobs as programmers easier.
Before delving into the new features he is adding, Rich provided a summary of how Clojure is implemented. Part of it is written in Java for performance, and the rest is written in Clojure itself. He said his goal is to eventually write most of Clojure in Clojure once he can get performance boosted to an equivalent level.
Clojure is built using abstractions, with those abstractions written as Java interfaces. The fundamental implementation objectives of Clojure (or at least the ones I picked up on), he said, are to leverage high-performance polymorphism mechanisms of the host environment, to write to abstractions not concrete types, and to enable extension and interoperability with Java.
From what I understood of the new language features, Protocols are named sets of generic functions. Reify allows developers to use the “cool code generation” in the built-in fn function. “I put a lot of work into ‘fn’ and I wanted to make it reusable,” he said. Even though it went over my head, Rich said Reify allows developers to create an instance of an unnamed type that implements protocols, like proxy for protocols. For the new Datatypes feature, if I understood correctly, he said he added a new construct, deftype, to define a name for a type and list of fields in that type.
Additional details that might make sense if you know Clojure:
- Datatypes fields can be primitives
- Datatypes support metadata and value-based equality by default
- In-line method definitions are true methods, no indirection or lookup and calls can be inlined by just-in-time compilers, like Hotspot
- Keyword-style field lookups can be inlined just like (.field x) calls
Rich concluded by offering more reasons to explore and begin using Clojure. “Closure has dramatically less implicit complexity than other languages,” he said. You don’t need to write a lot of code simply to support the needs of the language. You spend your time with Clojure focusing on domain complexity, not language complexity, he said. “It has a lot of newness, so the unfamiliarity level is high,” he said. “But it is very, very simple.”