NOTE: This article was written for something other than google sites. It seems that google sites won't
What you'll find here
Clojure is a relatively new lisp variant that's been attracting
a lot of attention lately. Part of the reason is that it runs on
the JVM, making integration with Java and other JVM based
languages, and access to all those nice Java libraries,
easy. Unfortunately, this also means that it comes with a lot of
the Java infrastructure as overhead.
Fortunately, you can do a lot with clojure without drowning in
the Java infrastructure. The goal of this document is to help you
set up and use clojure with the minimum amount of Java
infrastructure knowledge. If you're already familiar with that
Java infrastructure, you're wasting your time reading this (unless
you're going to provide feedback, which is always appreciated). If
you're not fairly familiar with your computer and it's operating
system, you're also wasting your time reading this (with the same
caveat).
I'm a Unix user, so that's what's going to be the first options
here. Mac users are lucky — Apple switched to Unix a while
back, so most of this should apply unchanged. Where that's not
true, it'll be noted. Windows users will have more differences to
deal with. I'll try to note them, but haven't been able to test
them, so corrections are welcome. Sorry about that, but I can't
provide information I don't have.
A note on example code: the computer output is always shown in
a red color. Variables that
you'll need to replace in scripts use THIS
font.
As a final note, this document may appear long. That's partly
because it deals with multiple platforms and options, but it's
also partly because it's not just a howto — I try and
explain what's going on, so that when someone has problems I
didn't cover, they have a chance of figuring it out and fixing it
for themselves.
Java Installation
You have to have a Java system installed. Hopefully, you've
already got it. If not, and you're on Unix-like system, your
package manager should install it for you. Otherwise, go to OraSuns java download
page, find "Java SE", and download and install the latest
version of the JDK. You can install other bundles if you want, but
the point of this page is that you don't need more than the
JDK.
Clojure Installation
The simplest way to install clojure is using your systems
package manager, if possible. I don't know what system you have,
so I don't know anything about your package manager. If you use
Unix and don't know about your package manager, either consult
your systems administrator or use the manual install section.
Mac users have a choice of three different package managers: fink, MacPorts, or pkgsrc. Clojure
has been reported in the MacPorts system, but I haven't checked
myself. Installing some of these may well be more work than just
installing clojure manually.
As far as I know, windows doesn't have a package manager, so
skip down to the manual installation
section.
Package manager installs
Before doing an install with the package manager, check what
version of clojure is installed, and then go to clojure
downloads page and see what the latest release version
is. That is tagged as Featured on the downloads page. If
your package manager isn't installing the latest release, then you
can either bug the maintainer for that package, or go ahead and do
a manual install.
After installing clojure with your package manager, check the
list of files installed. You should find at least two files, and
possibly more. Most important is clojure.jar. You'll
need to note what directory that is installed in, as it is the
JARDIR referred to later in this document. There should
also be a file somewhere along the path named clojure
or clj or something similar, to be know as
CLJCMD from here on out. Running that should start the REPL. Finally, there may be a
clojure–contrib.jar. If that's there, you're
done, and can skip down to editors. If it's
not there, then skip to the instructions for installing contrib in the manual installation section.
Manual installation
Clojure
Clojure proper is very easy to install — it's just a
java jar file. Download the latest release from the clojure
downloads page. This should be the one tagged
Featured. Pick a directory to put it in that suits
you. Personally, I use ~/.clojure, but you can use
~/lib/clojure or ~/Library/Clojure on a
Mac. We're just going to use it as a place to hold jar files; the
name isn't otherwise important. I'm going to call it
JARDIR in the sequel.
At this point, you can test that things are working
properly. At the shell, run the command:
java -cp JARDIR/clojure.jar clojure.main
That should start the REPL. See the section on
it for what the REPL should look like. Use Control–D
(Control–Z on Windows) to exit it. If that's not what you get,
see the problems section.
Contrib
If you managed to install the clojure jar, then
clojure-contrib is no harder. Go to the clojure–contrib
downloads page and get the version that corresponds with the
version of clojure you are using. This should be the latest
release. Note that versions flagged as "–RC#" are
not releases, but candidates for a release. Avoid them.
After you've downloaded and dearchived the file, copy
clojure-contrib.jar to JARDIR alongside
the clojure.jar file. If you are installing
clojure-contrib after installing clojure with a
package manager, you'll want to read the section on the command and possibly tweak the
CLJCMD script just a little.
You can test that you've got the contrib library installed
properly at the REPL. First start clj with this command (not quite
the same as last time):
java -cp "JARDIR/clojure.jar:JARDIR/clojure-contrib.jar" clojure.main
Clojure 1.1.0
user=>
Now, at the user=> prompt, try using the
library. That should work something like so:
user=> (use ['clojure.contrib.def :only ['defn-memo]])
nil
user=> (doc defn-memo)
-------------------------
clojure.contrib.def/defn-memo
([fn-name & defn-stuff])
. . .
The use expression loads the
defn-memo macro from the clojure.contrib.def
namespace, then we use the doc macro to ask for
information about it. Use Control–D (Control–Z on Windows) to exit
the REPL. Again, if you don't get output that is fundamentally
what is shown above, then something is broken, so see the problems section. Otherwise, it's time to
make things a bit easier to use.
The command
OK, you've now got clojure installed, along with the contrib
libraries, and are ready to start trying to write code. Except if
you installed it manually, you have to remember that ugly long
java command every time, or if you installed a package that didn't
include the contrib library you have a command that doesn't let
you use the library. We're going to fix that.
Those of you familiar with Unix scripting (or Windows
scripting, for that matter) should have a good idea of what to do
next. We're going to create a shell script (bat file) to run the
command. If you installed a package, then you already have
that. If you're going to create a new one, it looks like so:
#!/bin/sh
java -cp "JARDIR/*:." clojure.main "$@"
Note that if you installed clojure with a package manager, the
critical change is to the -cp or
-classpath option to the java command, or possibly to
the CLASSPATH environment variable. For best results,
try replacing clojure.jar (or the equivalent) with
\*.
For windows, the bat file looks like:
@echo off
java -cp "JARDIR\*;." clojure.main %1 -- %*
This is the simplest thing that should work. The magic you need
to understand is the value of the -cp option. This
tells java where to look for classes. In particular, we tell it to
look in all the jar files in JARDIR with
JARDIR/*, quoted so that the
* isn't expanded by the shell, and in the current
directory (.). The two are separated by a
:. Both of those need to work. Save the text in a
file called clj or clojure
(CLJCMD from here on out) somewhere in your path, then
run chmod 755 CLJCMD to make it
executable. Try running it with no arguments and verify that you
get a REPL. Exit that with Control–D
(Control–Z on Windows), and try running the script again
with --help as a lone argument. You should get a help
text that starts with something like:
Usage: java -cp clojure.jar clojure.main [init-opt*] [main-opt] [arg*]
With no options or args, runs an interactive Read-Eval-Print Loop
If you get that, congratulate yourself, you've successfully
installed clojure. Wasn't that hard, was it? You can go look at
the Tweaking the environment section for some
pointers on how to make it better. If not, try changing the script
to read:
#!/bin/sh
JARDIR="JARDIR"
java -cp "$JARDIR/clojure.jar:$JARDIR/clojure-contrib.jar:." clojure.main "$@"
For package manager installs, we're changing the same value,
but this time instead of replacing clojure.jar, we
append a :, the directory name again and then
clojure-contrib.jar.
For windows, this one looks like:
@echo off
set JARDIR=JARDIR
java -cp "%JARDIR%\clojure.jar;%JARDIR%\clojure-contrib.jar;." clojure.main %1 -- %*
The only change is that you're listing the two jar files
explicitly instead of passing a * to the JVM to tell
it to find them all, because some older JVM's may not understand
the latter. This will make working with other Java libraries
harder, but is otherwise pretty much insignificant. If that
doesn't work, try the problems
section.
The REPL
The REPL (as a reminder, that's the Read Eval Print Loop) is the single most important tool in a lisp
programmers tool box. If you're familiar with them, you can skip
this section. When it's started, you should have a terminal window
displaying something like:
$ CLJCMD
Clojure 1.1.0
user=>
If you don't get that prompt, something is broken, so read the
problems section for troubleshooting
advice. If not, then you now have the ability to type clojure
expressions and see their value, ask for documentation on
clojure's builtin functions and macros, and search the
documentation for functions. Since clojure functions are defined
with clojure expressions, you can write and test functions at the
REPL. It's your new best friend — at least when writing
clojure.
The most important thing to know about the REPL is that it
evaluates clojure expressions, which are either literal values or
function invocations of the form (function argument
...), and then prints the value of that
expression. Some simple examples are:
user> "Hello World!"
"Hello World!"
user> (println "Hello World!")
Hello World!
nil
user> (+ 3 5)
8
user> (* 8 5)
40
user>
More immediately useful, you can ask the REPL for documentation
on a function or macro that's part of clojure, using the
doc function and then the name of the function or
macro. Try it now with (doc println). Now ask about
+ and *. Even better, you can search the
documentation with (find-doc "thing"),
which will find all the functions or macros that mention thing. If
you read the docs on doc and find-doc,
you'll see that there's even more power lurking in them.
Editors
As cool as the REPL is, typing programs into it over and over
again gets old pretty quickly. So clojure lets you store them in
text files. All you need is a text editor with a couple of common
features, pretty much any editor will do, so try your favorite
first. If your favorite is some fancy IDE, that will almost
certainly work.
The first feature is parenthesis matching, meaning you can
point out a paired character like (), {} or [], and the editor
will indicate where the matching character in an expression that
included nested pairs, etc. Or it may indicate an error, if what's
inside the pair in question isn't balanced.
The second feature is simple auto indentation, meaning that if
you hit newline, it should prepare you to start typing at the same
indentation level as the previous line.
If you've got those two, you're ready to write clojure code. If
not, you may need to turn them on in your editor. If your editor
doesn't have those, you either have to live without them, or
change editors. Jedit is a
popular cross–platform programmers editor; you might try it. Up to
you whether to install it via your package manager or from the web
site. Once again, look at Tweaking the
environment section for how to make the environment nicer.
Running code
You've got a clojure command that can start a REPL and an
editor, so it's time to write some code.
A first script
Try saving the following in a text file called
greet1.clj (leave the first line off if you're on
Windows):
#!/usr/bin/env CLJCMD
(defn greet! [name]
(println "Hello" (str name "!")))
(greet! (apply str *command-line-args*))
You can now run it using CLJCMD greet1.clj
Joe, and it should respond with Hello Joe!. Try using the
doc function to figure out what's going on here. One
clue: defn defines a function.
If you're on a Unix system, you can make the script directly
executable by changing it's mode to 755. The best you can do with
Windows is to create a batch file.
Scripts that use scripts
Only small programs fit nicely in a single file — even in
a language as powerful as clojure. You can load functions from
another file very easily. Try the following second script:
#!/usr/bin/env CLJCMD
(use 'greet1)
(greet! (apply str *command-line-args*))
And then run it with CLJCMD greet2.clj
Joe. It prints the output from the invocation of
greet! —. Twice. Then it throw an exception,
complaining about namespace 'greet1' not found after loading
'/greet1'.
OK, the duplicate print is easy to explain: we call
greet! twice. Once in greet1.clj, and
once in greet2.clj. The other error is the Java camel
poking it's noise into our clojure tent. When you use
a file, you are actually using a namespace. Java applications
— including clojure — find the namespace by looking
where it expects the file to generate the namespace in question to
be. It found the file, but the file didn't create the namespace,
so clojure complains on exit.
To fix this, create greet3.clj that is almost identical to greet1.clj:
#!/usr/bin/env CLJCMD
(ns greet3)
(defn greet! [name]
(println "Hello" (str name "!")))
We've taken out the invocation of greet! that was
in greet1, which will remove one of the output
lines. We've also added an invocation of the ns macro
to create a namespace called greet3 where the code in our file
will be. After changing greet2.clj to use greet3
instead of greet1, run it again. This should just print our
greeting.
Note that the use is obsolescent; you should
actually use the :use keyword of the ns
macro. Either one has much more power than shown here, allowing
you to selectively import functions, or exclude them, etc.
Dipping a toe into the Java
Dealing with namespaces
Continuing with namespaces, the Java convention is that the
namespaces for your published code should be drawn from the
internet's domain name system, only backwards, to prevent clashes
with other people's libraries. To comply with that, I would call
our scripts above org.mired.greet#.
That's not so bad, but when searching for a namespace, java
searches for it in two sets of places. One is inside all the jar
files on the classpath (that's the value of the -cp
option in our script), and the other is in the directories on the
classpath. The catch is that each dot in the namespace translates
to a sub directory to look into. So java (and hence clojure) will
look for org/mired/greet1.clj instead of
greet1.clj if I (use greet1). Working
with this with conventional UNIX tools is a pain — you run
your commands in one directory, but edit files somewhere else
entirely. Java IDEs deal with this for you — it keeps the
list of files handy for you to select from. Likewise,
Java–influenced clojure tools like leiningen know about this
— they'll let you execute or edit a "namespace" and look for
it in the right place in the directory tree.
If you're not using a Java IDE, and not planning on publishing
your application, I recommend you ignore the convention. Just keep
your files in the top level directory and sub directories as you
would with a language without that convention.
If you want to use the "conventional" namespaces, but also
don't want to deal with the deep directory structures, you can
finesse the issue by creating all but the last level of the
directory structure, then symlinking that name back to the top. So
I have:
bhuda% file org/*
org/mired: symbolic link to `..'
This causes clojure to look for org.mired.foo in
the current directory. Source for other org domains will be
created normally. If I create a package that has it's own class
files in org.mired, then I create a directory in the
current level, just like I'd do with any sane language. This may
cause problems if I want to create a package whose name matches a
top level domain, but I'll live with that restriction in order to
be able to keep my files where I want them.
On a related note, if you don't have a domain of your own, you
can still publish your code with a conventional namespace. Chances
are, one or more of the sites involved in publishing your code
will provide an acceptable name. If you're going to publish your
application on sourceforge, then
appname.sourceforge.net points to a page you can edit
on sourceforge; that will work fine. Ditto for
username.github.com if you're going to publish on
github. If you're going to publish on a blog, there's a good
chance it has it's own domain name (e.g.
mired.wordpress.comor
miredincode.blogspot.com) that you can use.
Failing that, you can just make up something and put your name
in it. But you're no longer in a managed name space, so doing
something like names.meyer.mike could run into
trouble (there are a lot of me out there!) later.
Libraries
Using third party java libraries, fortunately, is much easier
than dealing with namespaces. Once you've got the jar file for the
library, just copy it into JARDIR. You then access
those namespaces in clojure with the import function,
or (preferably) the :import keyword of the
ns macro.
For example, to use Sun's experimental comm port IO libraries,
I put the collection of jar files I download from Sun in my
JARDIR, then add an import to my code:
(ns org.mired.commapp [:import javax.comm.CommPortIdentifier])
and then later in the code access it via the Java interoperability
capabilities:
(defn getport [name]
(.open (CommPortIdentifier/getPortIdentifier name) "output line" 2000))
The one catch is if you're not using the /*
version of the clj script. In that case, you have to add each jar
file to the -cp option value.
Compilation
You will have noticed that the scripts run really slowly, at
least compared to other scripting languages. That's because, well,
you have to load the Java vm, then the clojure libraries, then
compile the clojure before you can run it. Most of these things
weren't designed to be used as part of a scripting language; they
were designed to build enterprise systems, where a few seconds of
startup time are negligible. However, see Tweaking the environment for an
alternative solution.
The obvious solution is to compile your clojure. That doesn't
really cut down the time much, though. You still have to load the
java vm and clojure libraries. Since clojure compiles the code,
all you really need to do is save the compiled code to disk. To do
that, make sure you have a classes sub directory in
your top level source directory, and the appropriate namespace
tree in classes as well, and add
(:gen-class) to the ns macro in each
file. Finally use (compile 'namespace) to
compile the code in namespace. This will create Java
class files that will get used if you add ./classes/
to the -cp argument to java in your
CLJCMD.
Of course, eventually what you will want is a jar files of your
clojure application. That involves compiling the clojure code as
above, then using the jar command to create the jar file. This is
the point where avoiding Java is no longer simple. You could try
using make or a similar tool to drive the process, but you'll
still have to deal with the minutia of the jar command. Using the
Java infrastructure tools for this isn't noticeably harder than
doing it with make and friends. Actually, the same is true for
using those tools rather than trying to compile more than a few
clojure source files without them. The clojure community seems to
be settling on leiningen
for these kinds of things, but there is still a lot of support for
tools that tools that aren't so clojure specific.
For the record, if you want to bundle just one class, start by
making sure the classes directory (above) has only the files from
that class in it, then create a manifest.txt file
that contains the string "Main-Class: classname" - with
classname being the name of the class being
bundled. Now run the jar command jar cvfm
classname.jar manifest.txt
classfiles. The classfiles should be
a regexp that lists all the .class files created by
the (compile) step. That will create
classname.jar, and you can move that to
JARDIR and then use it like any other jar library.
The default name for the procudure java will run if you try
running just that class is "-main". It will be passed the command
line arguments as a sequence of strings.
Addendum: Tweaking the environment
At this point, you have everything you need to start working
with clojure. However, the environment is primitive. Following are
some things you can do to improve things. They aren't required,
but will make life more pleasant.
The REPL
If you're on a Unix system, I recommend installing and using
the rlwrap
command, either from your package manager or from the author. This
provides emacs–style command line history and editing by
default, but can be configured to give you vi if you prefer. The
CLJCMD script should change to look like:
#!/bin/sh
JARDIR="JARDIR"
if [ "$#" -eq 0 ]
then
rlwrap --command clojure --quote-characters='"' java -cp "$JARDIR/*:.:./classes/" clojure.main "$@"
else
java -cp "$JARDIR/*:.:./classes/" clojure.main "$@"
fi
If you're using the version that lists both
clojure.jar and clojure-contrib.jar as
part of the argument to the -cp option, use that on
both lines.
If you're using windows, get the jline
library, unzip it and install the jar file and copy it to
JARDIR. Then if you aren't using the \* version of
the batch script, change it to add the jline jar file, plugging in
the right version number:
@echo off
set JARDIR=JARDIR
IF (%1)==() (
java -cp "%JARDIR\jline-VERSION.jar;%JARDIR%\clojure.jar;%JARDIR%\clojure-contrib.jar:." jline.ConsoleRunner clojure.main %1 -- %*
) ELSE (
java -cp "%JARDIR%\clojure.jar;%JARDIR%\clojure-contrib.jar:." clojure.main %1 -- %*
)
If the \* version works for you, then you don't
need to add jline-VERSION.jar to the
command line. That's the advantage of that version.
jline also provides command line editing and history, but
configuring it requires wading through the Java class docs. rlwrap
works better out of the box, and has a man page, meaning it can be
configured without having to wade into the Java infrastructure,
and avoiding that is the goal here.
Editors
If you're using a fancy Java IDE, then why are you reading
this? You should already be familiar with all the Java
infrastructure I'm helping people avoid learning about. But since
you're here, check the plugins/modes/whatever they're called in
your IDE, to see if it already has clojure support. If so, it
should provide better auto indentation, syntax highlighting and
maybe better REPL integration. Recent versions of Jedit provide
this. If not, or if you're using an editor, google for clojure and
your IDE or editor name (but not emacs!). You may well find pages
to help you configure them to make writing clojure easier.
If you're using emacs, congratulation. Your help is here. You
want to install clojure-mode.el from github. Since
emacs is your favorite editor, I'll assume you know how to install
such. This should give you smarter indentation, syntax
highlighting and the ability to send code to an inferior
clojure. You might also consider paredit
mode if you aren't already using it. If you're used to using
SLIME for dealing with lisp inside of emacs, you may also want swank–clojure
to connect them up. If you're not using SLIME, I'd leave it until
later. It provides a better environment, but has a history of
being painfull to install.
GUIs
I don't do GUIs. A mouse is just to low bandwidth a device for
a lot of tasks, and people who want GUI should just boil up a
batch of okra. Me, I like my okra fried.
If you've got a Mac, you probably don't agree with me. In that
case, there's a tool called Platypus that can
wrap your CLJCMD with a clickable icon. The script to
use is open -a Terminal CLJCMD. This won't
let you double–click a clj file to run it, or drop clj files on
your clj script. It will create an icon that will launch a
Terminal window running your REPL when double–clicked. Platypus
can also be used to turn clojure scripts into clickable icons that
generate text or HTML output, or a progress bar, etc.
Once you start getting into the Java infrastructure, you can
use jarbundler
— also available in some of Suns developer toolkits —
to create conventional Mac applications from jar
files. Presumably, a similar tools is available for Windows.
Performance
There is one thing you can use to improve the performance of
clojure scripts without having to get further into the Java
infrastruture: nailgun. This
consists of a server — written in Java — that runs in the
background, and a client — written in C — that talks to the
server. The first time you run a java application on the nailgun
server, it will have to load the jar files, but java is already
loaded. The second time, the jar files are loaded, so your
application starts almost instantly.
To use it with clojure, start the server with the same java
command you normally use (without rlwrap if you use that, but with
the jline jar if you use that), except use
com.martiansoftware.nailgun.NGServer instead of
clojure.main. You can then start clojure using
ng clojure.main arguments just like you
CLJCMD. If you use rlwrap for REPLs, pass it the ng
command instead of CLJCMD. If you use jline, then run
ng jline.ConsoleRunner clojure.main args
to start your REPL.
However, I don't recommend using nailgun for REPLs. Those tend
to be used during development, so broken things you defined in the
user namespace will persist across sessions — meaning you can't
just start a new session to clear out all the development code!
Given that REPLs tend to be around for a while, the startup
overhead is minimal compared to this problem. For scripts, on the
other hand, you reload the script file each time, so that's not an
issue, and the time savings from not loading java and jars needed
can be significant.
Problems
As a first step, try and go back over the process so far and
figure out what's wrong. Some things to try include making sure
that the shell (.bat on Windows) script and java executable are in
your path and flagged as executable. Double check the expansion of
JARDIR in the script, and that the * is properly
quoted there as well.
If none of the above helps, read the smart
questions writeup if you haven't read it before. Finally,
record what you've done so far, what you did that doesn't return
the right result, the result you expected, and the result actually
got. Send that to clojure@googlegroups.com.
That's preferable to contacting the author - he'll read it there
as soon or sooner than he would if you send it directly, and
someone else may get you an answer even faster.