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!**
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.