One of the main advantages of Clojure (and Lisp) is interactive development, the REPL is the base of what can be achieved with interactive programming, it allows you to connect to a running VM running Clojure and execute or modify code on the fly.
There is a story about how NASA was able to debug and correct a bug on a $100 million piece of hardware that was 100 million miles away (http://www.flownet.com/gat/jpl-lisp.html).
We have that same power with Clojure and Leiningen and invoking it is very simple, you just need a single command:
This is what you'll get after running the preceding command:
Let's go into a bit more detail, as we can see we are running with the following programs:
We can also get some nice suggestions on how to see documentation, source
, Javadoc
, and previous errors.
One particular thing that is important to note is the nREPL protocol; Someday it might grant us the power to go into a machine running 100 million miles away.
When you fire up your REPL, the first thing you see is:
What it is saying is that there's a Clojure process running an nREPL server on port 55995
. We have connected to it using a very simple client that allows us to interact with the Clojure process.
The really interesting bit is that you can connect to a remote host just as easily; let's try attaching an REPL to the same process by simply typing the following command:
Most IDEs have a good integration with Clojure and most of them use this exact mechanism, as clients that work a little more intelligently.
Now that we are inside the REPL, (any of the two) let's try writing our first expression, go on and type:
You should get back a value from the REPL saying Hello world
, this is not really a program, and it is the Hello world
value printed back by the print phase of the REPL.
Let's now try to write our first Lisp form:
This first expression looks different from what we are used to, it is called an S-expression and it is the standard Lisp way.
There are a couple of things to remember with S-expressions:
- They are lists (hence, the name, Lisp)
- The first element of the list is the action that we want to execute, the rest are the parameters of that action (one two three).
So we are asking for the string Hello world
to be printed, but if we look a bit closer at the output, as shown in the following screenshot, there is a nil
that we weren't expecting:
The reason for this is that the println
function returns the value nil
(Clojure's equivalent for null) after printing Hello world
.
Note
In Clojure, everything has a value and the REPL will always print it back for you.
REPL utilities and conventions
As we saw, the Leiningen nREPL client prints help text; but how does that work? Let's explore some of the other utilities that we have.
Try each of them to get a feeling of what it does with the help of the following table:
Let's check how these functions work:
Tip
Downloading the example code
You can download the example code files from your account at http://www.packtpub.com for all the Packt Publishing books you have purchased. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.
What you are seeing here is metadata pertaining to the doc
function; Clojure has the ability to store metadata about every function or var
you use. Most of the Clojure core functions include a doc string and the source of the function and this is something that will become very handy in your day to day work.
Besides these functions, we also get easy access to the latest three values and the latest exceptions that happened in the REPL, let's check this out:
Note
*e
gives you access to the actual plain old Java exception object, so you can analyze and introspect it at runtime.
You can imagine the possibilities of being able to execute and introspect code with this, but what about the tools that we are already used to? How can we use this with an IDE?
Let's check now how to create a new Clojure project, we'll use Leiningen from the command line to understand what is happening.