If, like so many other developers, you suffer from a mild addition to Hacker News, then you've surely run across a reference to the Clojure language (pronounced "closure") more than once while perusing the latest headlines. A Lisp dialect targeting the JVM runtime, Clojure users stand to gain from the portability and stability of the JVM, the rich syntax of a functional language, and the ability to integrate with the enormous Java ecosystem. These advantages have clearly resonated with the programming community, as a swarm of activity has amassed around the language in the four years since its inception.
If you've been wondering what all the buzz is about, this article offers a practical, hands-on overview to Clojure, covering the installation process, basic syntax, and potential for Web development.
Clojure is available on all major platforms, including Linux/Unix, OS X, and Windows. You will, however, need to make sure Java is installed before proceeding. (See this link to determine whether Java is already installed on your computer). Linux/Unix users will almost certainly be able to install Clojure via their package manager. For instance on a Debian-based system such as Ubuntu, you can install Clojure by executing the following command:
$ sudo apt-get install clojure
OS X users can install Clojure via MacPorts:
$ sudo port install clojure +rlwrap
Windows users can install Clojure and several other useful Clojure-related tools using Clojure Box.
Barring any of the aforementioned solutions, or if you want to be certain you've installed the very latest stable version, download the code by cloning Clojure's GitHub repository:
$ git clone git://github.com/clojure/clojure.git
Using the REPL
The easiest way to begin experimenting with Clojure is via the REPL (read-eval-print-loop) command-line interface. If you're not familiar with functional programming syntax, the REPL is a great place to begin learning because it offers an easy way to execute commands repeatedly and view the outcome.
Windows users can interact with the REPL via SLIME, which is bundled with Clojure Box. See this video for more information. Linux/Unix and OS X users can start the REPL by executing
clj on OS X) via the command line:
$ clojure Clojure 1.1.0 user=>
In my opinion, Clojure's prefix notation is the one feature which requires the most adjustment on the part of the programmer. Prefix notation dictates that the function is identified before the arguments. Consider the following addition operation:
user=> (+ 2 5) 7
The first thing you've undoubtedly noticed is the parentheses. Anything provided to Clojure must come in the form of a list, with lists consisting of code and data. In this particular example the "code" is the addition function, which happens to be named
+, and the code, or arguments, are
5. So what about variable (known as a binding in Clojure) assignment? Indeed, you'll use a function (
def) to perform the assignment:
user=> (def minutes 60) #'user/minutes user=> (def hours 24) #'user/hours user=> (println "Minutes in day: " (* minutes hours)) Minutes in day: 1440 nil user=>
So far so good. But other than a different syntactical approach we really haven't seen anything which separates Clojure from other languages. Clojure's unique (relative to non-functional languages) capabilities begin to grow apparent when considering the succinctness with which it can execute manipulation tasks such as map, filter and reduce. The following example demonstrates how Clojure can convert a collection of values representing Fahrenheit-oriented temperatures to Celsius:
user=> (map #(* 0.556 (- % 32)) [32 98.6 150]) (0.0 37.0296 65.608)
I think this simple example provides a pretty good idea of just how succinct yet readable Clojure programs can be!
Creating a Clojure Script
While the REPL is great for syntax experimentation, you are, of course, going to want the luxury of saving and executing your Clojure scripts. The following example will convert any temperature in Fahrenheit passed into the script as an argument into the associated Celsius-based value:
#! /usr/bin/env clojure (def fahrenheit (first *command-line-args*)) (println (* 0.556 (- (read-string fahrenheit) 32)))
Save this file as
convert.clj, change its permissions so the script is executable, and execute it like this:
$ ./convert.clj 98.6 37.0296