It is a need usually provoked after experiencing an emotional conclusion to a difficult life event, such as the breakdown of a close interpersonal relationship [or an unreliable concurrent program, editor] or the death of loved one [or an old familiar programming language, editor]... A person with a high need for closure prefers order and predictability and is decisive [...][selected, edited parts from Wikipedia on the need for closure ;-)]
I've just decided to put all my pet projects and programming languages aside to dedicate myself to learning one single language, with the ambition to eventually master it. That language is Clojure. To force myself to reflect on my learning process and to help the community to the best of my ability, I will write a number of blog postings about my experiences with Clojure. There is already a lot of truly outstanding quality information about the theory and ideas behind Clojure around the net (mostly this excellent quality is due to fact the the creator of Clojure, Rich Hickey, is a great speaker). However, to my knowledge, there is less information about how to actually program Clojure. So this series of postings will explore programming Clojure from a beginners perspective -- hopefully others may learn from my mistakes and insights. In other words: This series is about Beginning Clojure in Practice. Update: Sat. Oct. 18, 2008: A few points about Clojure, and links to better information. What is Clojure? Clojure is a relatively young language (recently, it's 1-year birthday was celebrated). As I am beginning clojure, I am certainly not the best source of information; however, I would like to share my personal top 5 reasons why Clojure stands out in the ocean of programming languages that seems to be growing only faster by the day. If you want to know more about clojure, I strongly encourage reading the entire homepage and watching the videos on blip.tv. Why Clojure?
- Clojure is a LISP (perhaps it is more precise to say that it is strongly inspired by LISP, in some sense it is more general). Most importantly this means the full power of macros.
- It is compiled to the JVM, and designed to embrace it. This means making use of a powerful infrastructure, e.g., garbage collection and a powerful, mature, optimizing JIT. Rich Hickey makes a good point on distinguishing languages that 'live on' the JVM (like JRuby or Jython) and languages that are designed for the JVM like (Groovy and Scala). Since JRuby and Jython are 'ports' of a language specified elsewhere, they have to fit on the JVM for better or worse (for example no call/cc in JRuby). In contrast, Clojure is designed for the JVM: Rich calls this 'embracing it.'
- Java interoperability. Clojure is designed to inter-operate with Java; there is language-level support [syntax, even ;-)] for interacting with Java (no wrappers). This means that the enormous number of already existing Java libraries can be used from Clojure. This solves the 'library problem' (see below).
- Clojure has an opinion about how to do in-process concurrency (my favorite point): First, immutability is good; it is the default, and all Clojure data structures are immutable. Yet, Clojure accepts that sometimes mutability is needed and even desired, and support for a mutability is provided in the form of Refs and Agents. These are programming language constructs that allow for mutability, but with a concurrency semantics. Refs come with a software transactional memory system, and agents allow an in-process asynchronous programming model (similar to, but not equal Erlang's actors). Go and read Rich's short essay: On state and identity; once you get a feel for the language, read it again ;-). Persistent data structures, are an amazing and important part of Clojure's concurrency model. This is what makes immutability viable in Clojure. An 'update' operation on a persistent data structure doesn't actually change the data structure (it is immutable), but returns a new data structure (also immutable) representing the updated structure. Now, one might think this entails copying the entire structure; amazingly via structural sharing this is not the case. Clojures data structures (e.g., a hash map) are immutable and persistent yet retain the performance guarantees of their mutable counter-parts (Rich claims performance from faster-than-Java to up-to at most 4x Java speed). More on this in a later posting.
- Dynamic and mostly functional; this speaks for itself.
So if LISP is still more powerful than Ruby, why not use LISP? The typical objections to programming in LISP are:My reply to this would be: Well, with Clojure, LISP is definitely going somewhere; only the second objection applies (and perhaps with time this will no longer be the case, who knows).
- There aren’t enough libraries.
- We can’t hire LISP programmers.
- LISP has gone nowhere in the past 20 years.