Meditations on programming, startups, and technology
New Relic

How to setup Clojure from scratch

My previous post about Clojure generated quite a bit of interest, so I thought I’d follow it up with something a bit more concrete. I primarily wrote this article for a friend who asked me for guidance on how to set it all up; and while this isn’t he only way to setup Clojure, I hope it will help other people who are also getting started with this great language.

As some people pointed out, setting up your Clojure environment can be slightly challenging. For example, when you install Ruby or Python, you can expect a Read-Eval-Print Loop (REPL) such as IRB or IDLE to be ready for you to use right out of the box, whereas the current version of Clojure (version 1.1) does not include an interactive top-level.

This post explains how to setup a Clojure environment step-by-step, including a working clj script (the common name for Clojure’s REPL). For this post I used the clj script contained within the Getting Started guide on Wikibooks as a base, but I built on top of it , so as to customize and improve it. In writing this post, I’ve made the assumption that you’re using a *nix environment. My instructions will be Mac OS X specific, even though it should be a breeze to adapt them for Linux, if required.

Step 1: Download and Build Clojure

The first step is to download and build the latest version of Clojure. (Please note, I used bit.ly below for code formatting reasons.)

$ cd /tmp
$ wget http://bit.ly/clojure
$ unzip clojure-1.1.0.zip
$ cd clojure-1.1.0
$ ant

This will generate several jars for us, including clojure.jar, which we’re interested in. Aside from clojure.core, we are also interested in clojure.contrib, a collection of useful libraries and functions that are often used in Clojure programs. To download and build clojure.contrib, follow these instructions:

$ cd /tmp
$ wget http://bit.ly/clojure-contrib
$ unzip clojure-contrib-1.1.0.zip
$ cd clojure-contrib-1.1.0
$ ant

This should generate a clojure-contrib.jar file. We can now proceed to copy both the clojure.jar and clojure-contrib.jar files to a convenient location. (You can copy the files with a single line, but for formatting reasons I split the operation into two copy operations).

$ mkdir -p ~/Library/Clojure/lib
$ cd ~/Library/Clojure/lib
$ cp /tmp/clojure-1.1.0/clojure.jar .
$ cp /tmp/clojure-contrib-1.1.0/clojure-contrib.jar .

Note that on Linux, you’d choose a different location (e.g., /opt/clojure/lib).

Step 2: Install rlwrap

Before we can proceed with creating a fancy clj script, we need rlwrap, which will make our interactive prompt much more friendly. On Mac OS X, if you are using MacPorts, you can simply run the following:

$ sudo port install rlwrap

Step 3: Create a clj script

Now we can finally finally create a clj script and save it as ~/Library/Clojure/clj:

#!/bin/sh
breakchars="(){}[],^%$#@\"\";:''|\\"
CLOJURE_DIR=$HOME/Library/Clojure/lib
CLOJURE_JAR=$CLOJURE_DIR/clojure.jar
CONTRIB_JAR=$CLOJURE_DIR/clojure-contrib.jar
CLOJURE_CP=$CLOJURE_JAR:$CONTRIB_JAR:$PWD

if [ -f .clojure ]; then
	CLOJURE_CP=$CLOJURE_CP:`cat .clojure`
fi

if [ $# -eq 0 ]; then
	exec rlwrap --remember -c -b $breakchars \
                -f $HOME/.clj_completions \
                java -cp $CLOJURE_CP clojure.main -i $HOME/.clojure.clj --repl
else
     exec java -cp $CLOJURE_CP clojure.main -i $HOME/.clojure.clj $1 -- $@
fi

Make it executable and symlink it to a convenient place on your path (e.g., ~/bin):

$ chmod a+x ~/Library/Clojure/clj
$ ln -s ~/Library/Clojure/clj ~/bin/.

At this point we almost have a working script. Before declaring it fully functional, let’s take a look at three files this script references:

  • .clojure: This file is optional and is located in the same folder as the scripts you want to execute. It can be used to include further jars in your classpath.
  • ~/.clj_completions: Includes a list of Clojure functions for tab completion (courtesy of rlwrap).
  • ~/.clojure.clj: Your Clojure startup file. It’s the first Clojure file that’s run when we start the REPL or execute a script. We’ll use this to add a couple of nice functions to the default clj REPL, but you can add anything you’d like to load at startup.

Step 4: Create a startup file

By default, clj will not have an exit function. You can either CTRL+D or enter a call to System/exit. This is not a big deal, but I like the idea of exiting with a simple (exit) call (as one does with Ruby and Python). Fortunately, we can add this function to the startup file. Furthermore, for learning purposes, few things beat having the source function which reveals the source code of built-in Clojure functions. This too can be added to ~/.clojure.clj:

(use 'clojure.contrib.repl-utils)
(defn exit [] (System/exit 0))

(exit) will now exit the REPL and source will reveal the source code as shown below:

user=> (source peek)
(defn peek
  "For a list or queue, same as first, for a vector, same as, but much
  more efficient than, last. If the collection is empty, returns nil."
  [coll] (. clojure.lang.RT (peek coll)))
nil

Step 5: Create a ~/.clj_completions file

As explained in the Clojure Wikibook referenced above, you can create the .clj_completions file by running the following from the REPL or as a script (e.g., clj myscript.clj):

(def completions
    (reduce concat (map (fn [p] (keys (ns-publics (find-ns p))))
                        '(clojure.core clojure.set clojure.xml clojure.zip))))

(with-open [f (java.io.BufferedWriter. (java.io.FileWriter. (str (System/getenv "HOME") "/.clj_completions")))]
    (.write f (apply str (interleave completions (repeat "\n")))))

This will populate the file .clj_completions with a list of 500+ symbols. You can now run clj and try tab completion by inserting a few characters and then pressing tab. For example:

mbp:~ acangiano$ clj
Clojure 1.1.0
user=> (re<tab>
re-find                ref-min-history        repeatedly
re-groups              ref-set                replace
re-matcher             refer                  replicate
re-matches             refer-clojure          require
re-pattern             release-pending-sends  reset!
re-seq                 rem                    reset-meta!
read                   remove                 resolve
read-line              remove-method          rest
read-string            remove-ns              resultset-seq
reduce                 remove-watch           reverse
ref                    rename                 reversible?
ref-history-count      rename-keys            
ref-max-history        repeat 

There you have it, a complete setup of Clojure from source to clj. You can find information about setting up your favorite editor/IDE on the Assembla Wiki.

Note: As pointed out by Phil and other commenters elsewhere, the easiest way to get started these days is probably to install cljr, a standalone REPL and package manager. My post outlines how to do it from scratch (as you can deduct from the title), just like we used to before these tools were released. You may however consider the pre-packaged solution instead.


If you enjoyed this post, then make sure you subscribe to my Newsletter and/or Feed.

receive my posts by email

11 Responses to “How to setup Clojure from scratch”

  1. David Backeus says:

    The packages above can also be installed through Homebrew packages clojure, clojure-contrib and rlwrap.

  2. Steve Miner says:

    wget is no longer a standard utility on Mac OS X. You can use ‘curl -O’ instead.

  3. Phil says:

    While I appreciate topics like this getting more coverage, I hope newbies don’t get the idea that it’s this complicated to get started with Clojure. These days it’s much easier to get started with a standalone repl using cljr or a project setup using Leiningen.

    • Hey Phil,

      thanks for stopping by. While there are easier ways these days, I wanted to show how to do it from scratch (ergo the title), because, contrary to popular belief, it’s not that difficult. I updated the post with your suggestion, though.

  4. anjan bacchu says:

    hi there,

    how about windows users ? step 1 and 2 seem to be similar assuming we have cygwin installed. How about other steps ?

    BR,
    ~A

  5. ScottM says:

    for some reason trying to perform step 5 completely kills my machine. can’t find out what’s broken as ps, top & activity monitor all hang

Leave a Reply

I sincerely welcome and appreciate your comments, whether in agreement or dissenting with my article. However, trolling will not be tolerated. Comments are automatically closed 15 days after the publication of each article.

Current month ye@r day *

Copyright © 2005-2012 Antonio Cangiano. All rights reserved.