Wednesday, February 25, 2015

Installing Clojure


In this post, we're going to install Clojure using Leiningen and run Clojure scripts from the command line, with optional arguments.

First, we need to make sure we already have Java on our system. Why Java? Because Clojure is hosted on the Java Virtual Machine (JVM) and its functions compile to JVM bytecode.

If the output of which javac isn't something like this, then get your JDK here.
$ which javac
/usr/bin/javac
Next, we get Leiningen, which is perfect for everything from package management to 'automating Clojure projects without setting your hair on fire'.


As it says on the official website, download lein, move it to your private bin, make it executable, and run. There's also a Leiningen installer here for Windows users.


1. Download lein.
2. Move it to your bin directory (Assuming the ~/bin directory exists and is added to the $PATH. If not, just create the directory and add it to ~/.bash_profile or /etc/paths, if you're on a Mac).
$ mv lein ~/bin/
3. Set it to be executable.
$ chmod a+x ~/bin/lein
4. Run it.
$ lein
Sit back and watch lein take care of installing itself and Clojure.

Start the Clojure REPL (Read–eval–print loop) using lein repl. The REPL prompt shows the name of the current namespace (*ns*), which defaults to user.
Type (println "Hello, world!") at the prompt. Hit enter.
$ lein repl

user=> (println "Hello, world!")
 Hello, world!
Seems familiar. Let's try something else.
user=> (+ 1 2)
 3
Notice anything different? Here's the thing. Every expression in Clojure is a list, much like other Lisp dialects. The first element of the the list is a function and the rest are arguments. And yes, that weird way of writing 1 + 2 is prefix notation. Don't worry about rewiring your brain for all that now; you'll get used to it.

Mmmkay. But, weren't we trying to learn how to run Clojure scripts from the command line? Like python filename.py or ruby filename.rb?

Fear not, there's a plugin for that!

Say hello to lein-exec.

We're going to install it as a global plugin so the exec task is always available.

Create a file called profiles.clj under ~/.lein/ and copy the following contents into it.
// ~/.lein/profiles.clj
{:user {:plugins [[lein-exec "0.3.4"]]}}
Run lein again to download the plugin into the "local repository" at ~/.m2/repository/.
$ lein
Now, you have the exec task available.
$ lein

Look! You can run short Clojure expressions right from the command line.
$ lein exec -e '(println "Hello, world!")'
Hello, world!
You can also type our incredibly complex code to display "Hello, world!" and save it in a file called hello.clj.
$ echo '(println "Hello, world!")' >> hello.clj
Run the file using lein exec.
$ lein exec hello.clj
Hello, world!
Cool. Now let's rewrite our program to accept command line arguments.
// hello.clj

(defn foo
"I don't do a whole lot."
[args]
(println args "Hello, world!"))

(foo *command-line-args*)
Let's define a function called foo, with the docstring "I don't do a whole lot." The function accepts arguments args and prints them out along with "Hello, world!"

From the lein-exec documentation, "Optional args after script-path are bound to clojure.core/*command-line-args*". We'll call the function foo, with our command line arguments using *command-line-args*.

Let's run lein exec again, this time with some creative arguments.
$ lein exec hello.clj arg1 arg2 arg3
(hello.clj arg1 arg2 arg3) Hello, world!
Aha! You can see that args is a collection with everything after the lein exec command.
Let's use the functions first and rest from the Clojure.core library to get the filename and our arguments seperately.

Now, our hello.clj looks like this.
// hello.clj

(defn foo
 "I don't do a whole lot."
 [args]
 (println "Filename: " (first args) "\nArguments: " (rest args) "\nHello, World!"))

(foo *command-line-args*)
Run lein exec again.
$ lein exec hello.clj arg1 arg2 arg3
Filename:  hello.clj 
Arguments:  (arg1 arg2 arg3) 
Hello, World!

See what happened? first returned the first item of the sequence args and rest returned the original sequence without the first item.

And that's the end of this post. So far, you've learnt how to install Clojure using Leiningen, install a lein plugin and run Clojure scripts with command line arguments. This should provide a convenient starting point to get your hands dirty with Clojure. You are ready to start Lesson 1 of Fast Track Clojure.