« January 2009 | Main

July 05, 2009

"Take this REPL, brother, and may it serve you well."

Clojure_300x300.png

I have recently started playing with Clojure. Like ANTLR it also has the trinity of technology, documentation, and tools. On the technology side Clojure is as Lisp dialect that runs on top of the Java Virtual Machine. For me, it has three outstanding features. These are superb Java integration, its concurrency features especially software transaction memory, and the lazy sequence library.

Clojure has very good Java integration. Calling Java code is easy and direct. Classes in the java.lang package are imported automatically. Classes in other packages can be imported using the (import ...) form. Java objects can be created using the (new classname...) form or the (classname. ...) macro. Calling methods is just as easy.

Clojure includes both an interpreter and a compiler. The compiler compiles Clojure code to Java byte code in standard Java class files, so Clojure code can be called from Java code easily. In addition Clojure provides a (proxy ...) macro, which creates a proxy class, of a particular type, and sets the implementation for some or all of the methods of the interface. This is useful when calling Java code that need callback classes, such as, for example a SAX ContentHandler. For Java code that need Runnable or Callable objects, the (proxy ...) macro is not even needed, as all Clojure functions automatically implement both these interfaces.

Clojure also includes functions to generate primitive Java types and arrays and to work with Java primitive arrays.

The second outstanding feature is concurrency support. In addition to all the Java concurrency features, Clojure has two extra features to enable ease development of programs which need concurrency. These features are Agents and Software Transaction Memory. By default data is immutable in Clojure: once a data binding is set, it normally cannot be changed. Refs are an exception to this. They can be changed but only in the context of a transaction in the Software Transactional Memory (STM). STM is the in memory reference analogue of database table transactions. Agents are another exception. Updates to agent values are done by sending asynchronous messages using the (send ...) or (send-off ...) forms. The update message consists of an update function that is applied to the agent's data. The updates are are queued and handled atomically in a separate thread.

The last killer feature for me is the lazy sequence library. Clojure includes a library that allows for lazily evaluated sequences to be defined. This allows for infinite sequences to be defined: the elements in the sequence are only actually generated as they are needed, so memory is not wasted. If it turns out that only a limited number of elemnts are actually used, this can save quite a bit on processing time, too. All the main sequence processing functions, such as (map ...), etc., return lazy sequences, so lazy sequences end up being quite powerful.

Documentation is available at the REPL via the (doc ..) and (find-doc ...) forms. There is a fantastic book, published by the Pragramatic Programmers, called Programming Clojure. In this book the author, Stuart Halloway, gives a solid introduction to all of the features of Clojure. There are chapters devoted to macros, Java integration, Clojure's concurrency features, Clojure's sequence library, and the multimethod feature. All of these are accompanied by informative examples and each chapter ends with the application of the leasons to an extended example: a build DSL called Lancet. The book also contains a chapter on funtional programming, which deals with all the features that help with programming in a functional style, such as lazy sequences, partial function evaluation using the (partial ...) form, and the forms to enable efficient recursion. The book ends with a chapter called "Clojure in the Wild", which deals with real world issues with using Clojure, such as connecting to database, running unit tests, and building web applications with Clojure.

The final member of the trinity is tools support. A Clojure mode has been developed for Emacs, and Clojure support has been added to SWANK and SLIME. The three of these provide a very nice development environment for Clojure, with syntax highlighting, indenting, and an embedded and integrated REPL, for trying stuff out. All the SLIME key-bindings seem to do what is expected, though, I haven't used a lot of them yet as I am still getting used to the environment. However, documentation look up and the different evaluation options seem to work a treat. There are even a few humorous touches: the title of this post is one of the messages SLIME gives you when you change to a buffer to SLIME mode with M-x slime. All in all, the whole experience has taken me one step further along the path to The Dark Side regular Emacs usage.

The whole thing was very easy to set up: I just followed the instructions at this web page, and was up and running in about 5 minutes. A post on Bill Clementson's blog was also useful, though, it would probably be more useful for an experienced Lisper.

Technorati Tags:

Posted by JohnC at 11:18 PM