If you play around with Java, you are ready to run Clojure. If not, you will have to install the Java Runtime Environment (1.5+ is recommended), and Ant, if you want to build the Clojure sources. Download the current snapshot of Clojure from github, extract the archive, and fire off
ant. Once the build process is completed, you should have the file
clojure.jar. Fire up the Clojure “prompt”, as follows:
$ java -cp clojure.jar clojure.main Clojure 1.3.0-master-SNAPSHOT user=>
The Clojure prompt is now ready for your instructions. Let’s try a few of them:
user=> (clojure-version) "1.3.0-master-SNAPSHOT" user=> (print) nil user=> (print "Hello world") Hello worldnil user=> (+ 1 1) 2
(clojure-version) is a built-in function that returns the current version of Clojure. This also demonstrates how you call a function in Clojure. The
nil that you see appended at the end of the Hello World string is the return value of the function,
nil means nothing.
If you are familiar with any language of the Lisp family, you have definitely guessed correctly that Clojure is a Lisp dialect. Since I will not be talking about the basics of Lisp programming, you will benefit from this article if you are just a little familiar with a Lisp dialect. On the other hand, you could use this article as a starting point to learn Clojure programming, and get a feel of what Lisp is all about.
user=> prompt is what is known as the REPL, or the read-eval-print-loop. The REPL is your key to world domination. A little Java library called JLine will help you in your quest by enhancing the editing support of the Clojure REPL. Once the JLine JAR is in your
CLASSPATH, invoke Clojure REPL using:
java -cp jline-0_9_5.jar:clojure.jar jline.ConsoleRunner clojure.main
Let us now see how you can go about defining a simple function at the REPL:
user=> (defn hello [name] (println "Hello, " name)) #'user/hello user=> (hello "new guy") Hello, new guy nil user=>
Here is a line-by-line explanation of the above block of code:
defndefines a function;
hellois the function name; it takes one argument, name.
- Java programmers will easily identify the
#'indicates that the function just defined was stored in a Clojure variable.
useris the name of the current Namespace, and
hellois the function just defined.
- The function is called with the argument as a string:
- The expected output is printed.
nilis the return value of the
Working with Clojure source files
As you start experimenting more with Clojure, you will want to have your source code in a separate file, and then load it at the REPL. For example, here is a block of code that implements a simple number-guessing game:
;; Guess my number game ;; Clojure port of the Common Lisp source by Conrad Barski ;; in Land of Lisp, Chapter 2. ;; Amit Saha ;; globals (def small 1) (def big 100) (defn guess-my-number  (bit-shift-right (+ small big) 1)) (defn smaller  (def big (- (guess-my-number) 1)) (guess-my-number) ) (defn bigger  (def small (+ (guess-my-number) 1)) (guess-my-number) ) (defn start-over (def small 1) (def big 100) (guess-my-number))
Now, load the file in the REPL using load-file. Let’s assume you have the number 15 in your mind, and you challenge the program to guess it. Here’s what a sample session would look like:
user=> (load-file "guessnumber.clj") #'user/start-over user=> (guess-my-number) 50 user=> (smaller) 25 user=> (smaller) 12 user=> (bigger) 18 user=> (smaller) 15
Editing and IDE support
Clojure is supported by most IDEs and various other editors out there. Since I personally use Emacs, I used Jeffrey Chu’s Clojure mode to edit the Clojure source files.
Interaction with Java
One of the main features of Clojure, as a Lisp dialect, is that it gives you access to the vast Java toolbox. Next, we will look at some basic usage of Java classes from Clojure. This example is taken from the book Programming Clojure, by Stuart Halloway:
user=> (new java.util.Random) #<Random java.util.Random@173ec72> user=> (def rnd (new java.util.Random)) #'user/rnd user=> (. rnd nextInt) 1976620372 user=> (. Math PI) 3.141592653589793 user=>
Our modest experience with Clojure so far has involved only the core features, or Clojure Core, to be technically accurate. You could consider these as the built-in features of Clojure. However, sooner rather than later, you will probably need to access the Clojure features that are packaged as third-party libraries.
Clojure-contrib is a collection of name-spaces, each of which implements various additional features. These libraries are also candidates for inclusion in the Clojure core. There are also a number of other libraries, which can be found at clojure.org/libraries — and, of course, Github will have a number of others. For a ready-to-use collection of Clojure libraries, see clojars.org.
In the next example, we will use a Clojure library, Incanter, which is a Clojure-based R-like statistical-computing environment for the JVM. Let us utilise an easy-to-use build tool for Clojure, called Leiningen. It is designed to “not set your hair on fire” — so the Github page claims. It lives up to those words quite well, if my initial experience is any indication.
First, let’s set up Leiningen, and then look at a simple use-case of Incanter. Download the lein script and
chmod it to be executable. This shell script will be used to bootstrap Leiningen, and hence the first time you run it, it will download the Leiningen JAR in
$HOME/.lein. Next, add the location of your lein script to your
$PATH. Then, create a new project with:
lein new incanter_demo. This step creates a new subdirectory (
incanter_demo) for your project, with the following directory structure:
. |-- project.clj |-- README |-- src | `-- incanter_demo | `-- core.clj `-- test `-- incanter_demo `-- test `-- core.clj
project.clj has the metadata about your project: version information, description, dependencies, etc. As mentioned, we will be using the Incanter Clojure library; hence, we need to add a dependency on Incanter. We also need to set an entry point for our application. Here is what
project.clj looks like after these modifications:
(defproject incanter_demo "1.0.0-SNAPSHOT" :description "Demo app using Incanter" :dependencies [[org.clojure/clojure "1.2.0"] [org.clojure/clojure-contrib "1.2.0"] [incanter "1.2.3"]] :main incanter_demo.core)
Next, we will edit the core.clj file to the following contents:
(ns incanter_demo.core (:gen-class)) (use '(incanter core stats charts)) (defn -main  (println "Welcome to Incanter demo") (view (histogram (sample-normal 1000))))
Finally, we will build our Clojure app using
Cleaning up. - Downloading: org/clojure/clojure/1.2.0-master-SNAPSHOT/clojure-1.2.0-master-SNAPSHOT.pom from clojure Downloading: org/clojure/clojure/1.2.0-master-SNAPSHOT/clojure-1.2.0-master-SNAPSHOT.pom from clojure-snapshots Downloading: org/clojure/clojure/1.2.0-master-SNAPSHOT/clojure-1.2.0-master-SNAPSHOT.pom from clojars Downloading: org/clojure/clojure/1.2.0-master-SNAPSHOT/clojure-1.2.0-master-SNAPSHOT.pom from central Downloading: org/clojure/clojure-contrib/1.2.0-SNAPSHOT/clojure-contrib-1.2.0-SNAPSHOT.pom from clojure Downloading: org/clojure/clojure-contrib/1.2.0-SNAPSHOT/clojure-contrib-1.2.0-SNAPSHOT.pom from clojure-snapshots Downloading: org/clojure/clojure-contrib/1.2.0-SNAPSHOT/clojure-contrib-1.2.0-SNAPSHOT.pom from clojars Downloading: org/clojure/clojure-contrib/1.2.0-SNAPSHOT/clojure-contrib-1.2.0-SNAPSHOT.pom from central Copying 38 files to /home/gene/clojure/incanter_demo/lib Copying 38 files to /home/gene/clojure/incanter_demo/lib Created /home/gene/clojure/incanter_demo/incanter_demo-1.0.0-SNAPSHOT.jar Including incanter_demo-1.0.0-SNAPSHOT.jar Including jline-0.9.94.jar Including incanter-charts-1.2.3.jar Including jlatexmath-0.9.1-20100323.073428-1.jar Including incanter-1.2.3.jar Including congomongo-0.1.2-20100502.112537-2.jar Including jtransforms-0.9.4.jar Including optimization-0.9.4.jar Including incanter-excel-1.2.3.jar Including avalon-framework-4.1.3.jar Including logkit-1.0.1.jar Including jcommon-1.0.16.jar . . Created /home/gene/clojure/incanter_demo/incanter_demo-1.0.0-SNAPSHOT-standalone.jar
Now that you have the standalone JAR for your project, run it like a typical Java JAR:
$java -jar incanter_demo-1.0.0-SNAPSHOT-standalone.jar.
You should see the following output:
Welcome to Incanter demo -
You should also see the plot, as shown in Figure 1. Now, if you go back to the project directory and list the contents of the lib subdirectory, you will see a bunch of JARs — which are basically the dependencies you specified in the
It is to be noted here that the option
uberjar tells lein to build a standalone JAR for your application, so as to make it shareable. If, however, you just want to run your application, use
Having had a preliminary look at Clojure, the language, let us now learn a bit about using Clojure for Web applications.
Web frameworks for Clojure
While there is nothing to prevent you from using the Java Servlet API directly in your Clojure applications and deploying them as Web Archives (WARs), we will not do that today. Instead, we will take a brief look at one of the Clojure Web frameworks, Conjure. As the website claims, it’s a Rails-like framework for Clojure. How similar the two are can only be judged by a Rails aficionado, which I am not. So let’s use Leiningen to write a simple Web application using Conjure.
Create a new Clojure project; add conjure-core as one of the dependencies, and lein-conjure in the dev-dependencies list. The
project.clj should look like what’s shown below:
(defproject hello-conj "1.0.0-SNAPSHOT" :description "Hello Conjure!" :dependencies [[org.clojure/clojure "1.2.0"] [org.clojure/clojure-contrib "1.2.0"] [conjure-core "0.8.0"]] :dev-dependencies [[lein-conjure "0.8.0"]])
lein deps to download all the dependencies, which will be stored in the
lib/ directories. Now that the conjure plugin for Leiningen has been downloaded, let us convert this generic Clojure project into a Conjure project:
$ lein conjure new
This step will create a number of Conjure-specific subdirectories and files in the project folder, which you can view by using the tree command. Let us now test the working of our server:
lein conjure server. You should see something like what is given below:
DEBUG [conjure.core.db.flavors.h2]: Executing query: ["SELECT * FROM sessions LIMIT 1"] DEBUG [conjure.core.db.flavors.h2]: Create table: :sessions with specs: (("id" "INT" "NOT NULL" "AUTO_INCREMENT" "PRIMARY KEY") ["created_at" "TIMESTAMP"] ("session_id" "VARCHAR(255)") ["data" "TEXT"]) INFO [conjure.core.server.server]: Server Initialized. INFO [conjure.core.server.server]: Initializing plugins... INFO [conjure.core.server.server]: Plugins initialized. INFO [conjure.core.server.server]: Initializing app controller... INFO [conjure.core.server.server]: App controller initialized. 2011-02-13 16:09:37.909::INFO: Logging to STDERR via org.mortbay.log.StdErrLog 2011-02-13 16:09:37.911::INFO: jetty-6.1.14 2011-02-13 16:09:37.946::INFO: Started SocketConnector@0.0.0.0:8080 . .
Now, you can visit the URL
http://127.0.0.1:8080 and you should see a default Conjure home page, as shown in Figure 2.
Congratulations! You can change the default file, which is in
src/view/home/index.clj, and see the changes automatically; no server restart is required.
In this admittedly whirlwind tour of Clojure, we have taken a look at some of the basic features of this relatively new language, and have become somewhat familiar with its ecosystem. The next steps will have to be taken based on what your area of interest is.
Accessing SQL and NoSQL databases and multi-threaded applications (which, incidentally, happen to be one of Clojure’s selling points) are a couple of areas which can be immediately looked into, especially for building scalable Web applications. Before we part, here’s something the Android fans among you should love. There is a Clojure REPL application available in the Android market place, which you can install for free and program in Clojure on the go!