An Architect's View

CFML, Clojure, Software Design, Frameworks and more...

An Architect's View

Getting Started With Clojure

June 29, 2010 ·

There's a thread on the Clojure mailing list, started by folks new to Clojure, pointing out that it can be a bit daunting to get Clojure running in order to try out some basics. I figured I'd post a very short tutorial showing how to get a basic running environment and Hello World! compiled as a JAR and executable via Java.

First off, I'm going to assume you already have Java installed and on your path and I'm going to assume you have a Unix-like command line (so this is more for Mac / Linux users - but there is a lein.bat script available for Windows users on the Leiningen site... See the link from @Shantanu in the comments for Leiningen on Windows).

The easiest way to get Clojure running is to use the de facto standard build tool for Clojure called Leiningen. So we'll start by installing Leiningen:

You get Leiningen from github at this URL: http://github.com/technomancy/leiningen

Follow the instructions there to download the lein script and make it executable. Add it to your path (I put it in a bin folder in my user home directory since that's on my path).

Then get Leiningen to install the bits and pieces it needs to run:

lein self-install

Now you can create a Clojure project, called hello, to play with:

lein new hello
cd hello
lein deps
lein test

You'll see a single testcase which deliberately fails:

Testing hello.core-test
FAIL in (replace-me) (core_test.clj:6)
expected: false
  actual: false
Ran 1 tests containing 1 assertions.
1 failures, 0 errors.

Great! Clojure is installed in this project and working!

We'll come back to the project in a bit. To get a feel for Clojure, let's try out some basic stuff by starting a script console:

lein repl

You'll see something like:

REPL started; server listening on localhost:21604.
user=>

Check which Clojure version you're running by typing (clojure-version):

"1.2.1"
user=>

I'm using Leiningen 1.6.1 (as of July 6th, 2011) and it defaults to Clojure 1.2.1.

Type (println "Hello World!") and press return. You should get:

Hello World!
nil
user=>

Now let's define a function that does that:

(defn greet[] (println "Hello World!"))

The console will respond:

#'user/greet
user=>

Run the function: (greet)

You'll get:

Hello World!
nil
user=>

It prints Hello World! and returns no result (nil). Let's redefine it so it takes an argument:

(defn greet[who] (println "Hello" who "!"))

And now let's run that:

(greet "Sean")

You should get Hello Sean ! You can press control-D to exit the console.

Now we'll work on the project we created above.

In your favorite text editor, edit src/hello/core.clj - this is the basic source skeleton that Leiningen created for you above. We'll add our greet function to it and call it, so core.clj reads:

(ns hello.core)
(defn greet[who] (println "Hello" who "!"))
(defn -main[] (greet "Sean"))

The (ns hello.core) line declares the namespace (think Java package) in which the code lives. The -main function will be the regular Java main function - that's what the - prefix means.

We can run this via Leiningen:

lein run -m hello.core

The -m argument specifies the namespace in which -main is defined.

Now let's modify our script so we can compile it and run it via Java. First we'll update the namespace declaration to tell Clojure we want to generate a (Java) class file, we'll remove the spaces in the output by call str to construct a single string (so we need a space after Hello), and we'll change our main method to accept an argument:

(ns hello.core
    (:gen-class))
(defn greet[who] (println (str "Hello " who "!")))
(defn -main[who] (greet who))

We also need to tell Leiningen about our main class. Edit project.clj and add a :main declaration so it looks like this:

(defproject hello "1.0.0-SNAPSHOT"
  :description "FIXME: write"
  :dependencies [[org.clojure/clojure "1.2.1"]]
  :main hello.core)

Don't worry about the rest of it - that's part of the Leiningen / Maven magic used to ensure the right libraries are available.

Now tell Leiningen to compile your script and create a JAR that we can execute via Java:

lein uberjar

If you look in the current directory, you'll see hello-1.0.0-SNAPSHOT.jar and hello-1.0.0-SNAPSHOT-standalone.jar and it's the second one we'll use:

java -cp hello-1.0.0-SNAPSHOT-standalone.jar hello.core Sean

Congratulations! You have a standalone compiled Java version of your Clojure script!**

You can read more about Clojure on the Clojure website and the Clojure mailing list. Since the language is still evolving pretty fast, being on the mailing list is pretty much a requirement :)

Check out the links from @Shantanu and @Alex in the comments on this entry for more great resources on Getting Started With Clojure!

** Technically, the JAR contains the compiled version of your main class and all your source, as well as the Clojure runtime. Clojure is able to load source code at runtime and compile it to bytecode on-demand so you only need to compile the main class - so that it can be called by the Java runtime system.

Tags: clojure · oss · programming

10 responses

  • 1 fogus // Jun 29, 2010 at 6:46 PM

    <code>lein repl</code>
    You'll see:

    <code>Closure 1.1.0</code>
    <code>user=&gt;</code>

    We will?! We should file a bug report about that. ;-)

    :f
  • 2 Sean Corfield // Jun 29, 2010 at 7:00 PM

    Thanx for dropping by Michael!

    You might want to explain your comment for the benefit of my readers who might think there's genuinely a bug there... :)
  • 3 Eapen // Jun 29, 2010 at 9:35 PM

    On the last step
    java -cp hello-standalone.jar hello.core Sean

    I get "Exception in thread .... NoClassDefFoundError: hello/core" is missing.

    Any suggestions?
  • 4 Sean Corfield // Jun 29, 2010 at 11:23 PM

    @Eapen, check your classes folder - I bet it's empty? I'd guess you missed either the :gen-class in core.clj or the :main in project.clj
  • 5 Shantanu Kumar // Jun 30, 2010 at 3:15 AM

    Great article for the newbies! I posted about how to setup Leiningen on Windows -- feel free to link to it if suitable:

    http://charsequence.blogspot.com/2010/06/setup-leiningen-on-windows.html
  • 6 Alex Ott // Jun 30, 2010 at 5:50 AM

    I have introductory article on Leiningen at http://alexott.net/en/clojure/ClojureLein.html
    As information on Clojure it's also worth to view screencasts and lectures about Clojure - I collected them at http://alexott.net/en/clojure/video.html
  • 7 Eapen // Jun 30, 2010 at 6:32 AM

    Thanks Sean. I did miss the ":gen-class in core.clj" - sorry about that. Didn’t realize I missed a step.

    I am curious - how do you get rid of the space between "Sean" and the "!"?
  • 8 Sean Corfield // Jun 30, 2010 at 8:32 AM

    @Shantanu, @Alex, great links / resources! I'll add a rider to my blog post recommending folks check out those links.

    @Eapen (str "Hello " who "!") creates a single string out of the three elements. I wondered who was going to be the first to ask that :)
  • 9 Phil // Jun 30, 2010 at 10:29 AM

    Also be sure to check the official tutorial:

    http://github.com/technomancy/leiningen/blob/master/TUTORIAL.md
  • 10 Colin Yates // Jul 8, 2011 at 11:46 AM

    Excellent - many thanks (again!) for taking the time to help out the Clojure newbies :)