Clojure is a tool that enables interactive development and runtime inspection. Even when we work in other programming languages, Clojure can still be useful. Especially when that other language lives on the JVM.
Let’s take Scala for example. Scala has a REPL. The REPL can be used
to test-drive software in development. But it doesn’t really let you
inspect a running program when you didn’t start it with
console. So let’s use Clojure for that. We will walk through a simple
Scala program that allows runtime inspection of an otherwise unknown
We’ll need an sbt project for this example. Make a directory and put a
build.sbt in it. The only dependency in this example is Clojure.
1 2 3 4 5
src/main/scala/example.scala we add the following imports:
We’ll be using
Clojure’s Java API. In
var is a reserved keyword, so I’m renaming it to
I don’t like the backticks in my code.
Next, let’s create an object that will contain some random value:
1 2 3
Also, let’s create an
App so we can run our program with
If we would execute
sbt run, we would never know the value of
BusinessLogic. We could add a
println, but what if
x was a
and it’s value would change over time? Clojure lets us inspect this
value at any given point in time. We’ll start a
that is available since Clojure 1.8.0.
1 2 3 4 5 6 7 8
This may seem a little intimidating, so I’ll explain it line by line.
On line 2 we get a reference to Clojure’s
require so we can… yes,
require namespaces. On line 3 we read a string so we get the symbol
require needs to load the
clojure.core.server namespace. On
line 4 we get a reference to the
var. On line 5 we
define a bunch of settings. Their meaning can be found
In Clojure this would read as:
1 2 3 4 5 6
but since we’re coming from Scala and have to use Clojure’s Java API, it looks a bit more involved.
On the last line we invoke
start-server with said options. When we
sbt run again, the process will block,
:server-daemon was set to
1 2 3 4 5
This gives us the chance to connect to the socket repl with good ol' telnet:
1 2 3 4 5 6 7 8 9 10
See what we did there?
Clojure’s socket REPL also supports initialization via a JVM property.
To try this, add these lines to
App can now be reduced to something like:
1 2 3
This doesn’t do much except taking care that Clojure is initialized (for more info, read the last paragraph in this Stackoverflow answer).
This Scala example translates fairly straightforward to Java. Now don’t tell your boss you’re using a different programming language. After all, Clojure is just a Java library that gives you superpowers :-).
PS: it may be wise to turn this off in production because of the security risk; on the other hand, a Clojure REPL has saved my day more than once in the past!