Whenever I’m showing a newcomer to Clojure how to bring in code from other namespaces, I find myself apologizing that it’s a bit complex and confusing.
Now, I won’t spend time moaning about the current state of namespaces (see this Clojure mailing list discussion and the design discussion around namespaces in the Clojure Confluence ), but I thought it might be helpful to give an overview of the various calls you can make to require a Clojure lib
.
Let’s start a Clojure repl, where we’ll outline the baseline commands to pull in libs. If you don’t know how, download Clojure and use these instructions to get a REPL up and running. If you already have the jar, just fire up a repl using java -jar clojure-VERSION-HERE.jar
.
Later, we’ll see the ns
macro, which is much more idiomatic, and that’s what you’ll use in real Clojure projects. However, since require
, use
, and import
are what you’ll often use in the repl, and because those are used behind the scenes, we’ll start there.
The baseline: require
Let’s say we want to use some of Clojure’s built-in string operations. In the current version of Clojure (1.2), there’s a library called clojure.string
which contains some useful functions like split
, join
, and capitalize
.
Let’s try to use split
to break up the first line of a CSV file:
Whoops! We forgot to actually tell Clojure that we’re going to be using that namespace. There are a few namespaces (clojure.core
, clojure.set
, etc.) that get auto-required into the user
namespace when the repl starts up, but clojure.string
isn’t one of them. So let’s tell the repl that we’re going to be using clojure.string
:
Great, so that worked. Let’s take a moment to examine this, the most basic syntax for pulling in other Clojure code. require
is just a Clojure function that takes a few different types of arguments.
First, we could pass a single quoted symbol, and require
will make the namespace named by that symbol available with the full namespace/var-name
syntax in later code. We can also pass multiple quoted symbols:
Keep in mind that I’m starting a fresh repl for each of these examples, to demonstrate what happens the first time you load a lib
. In general, if you require a lib
a second time, nothing will happen.
There’s a way around that (mainly for interactive development), as we’ll see later on, but for now, just start up a new repl as you’re trying these out.
It’s worth noting here that the name of the lib
itself parallels the directory structure, so in order to require clojure.string
, you’d need a directory named clojure
relative to your classpath, and a file called string.clj
within that directory.
That particular case is already true within the Clojure jar
, but it’s something to keep in mind as you write your own Clojure code and have need to require it outside of the namespace where it lives.
There’s also a way to alias namespaces when you require them, such that you could refer to a string
namespace rather than a clojure.string
namespace, and you’d get the same result:
The strange looking quoted vector is a shorthand to avoid having to quote every individual symbol within the vector. You could type:
The same concepts apply to using requiring multiple namespaces: require
will take an arbitrary number of libspecs, such as the quoted symbol and vector we’ve just seen. You can also mix and match symbols with vectors:
One last way to use require
simplifies things when a prefix is the same in several libraries you want to load:
Here, clojure
is the prefix for both of the libraries we want, so we only need to type clojure
once. string
and test
are just libspecs in these situations, so you can use the :as
option here as well:
At this point, the variation between list and vector notation (parentheses and square brackets, respectively) may be driving you a bit bonkers.
Never fear, the main thing to remember here is that a libspec should be either a quoted symbol or vector. So whenever you want to use something like :as
, that thing (the libspec) should be a vector.
It’s become somewhat idiomatic to use lists for many other places we’ll see later, but often that isn’t actually enforced by the language, and there are in fact situations where either vectors or lists might make more sense than the other from a semantic perspective.
Phil Hagelberg has some thought-provoking advice on this matter. Just stick with the syntax you see here and in the Clojure documentation, remembering that you must use vectors for libspecs, and you’ll be fine.
If you’re interested, you can see more details about what happens under the covers by appending a :verbose
flag to the end of the argument list to require
(note that the :verbose
flag is outside the libspec vector that pulls in clojure.string
):
As you can see, clojure.core/load
does the low level loading, then we switch back to the user
namespace (loading clojure.string
made it the current namespace for a brief, shining moment), and finally we create an alias in the user
namespace so that we can refer to clojure.string
as simply string
.
You’ll see significantly more complex output from this if you do something similar with clojure.test
, as it requires other libraries itself:
That might have seemed intimidating at the start of the article, but you’re likely now at a point now where you can guess the things that are being required under the covers.
Finally, I promised an example of reloading code from a particular namespace for interactive development, so here’s how it works:
Nothing happens the second time, as you can see. However, we can change that with the :reload
flag:
As you’d expect, the code gets loaded again with the :reload
flag. The reload-all
flag works similarly, but it will also make sure that all dependencies of the namespace in question are also reloaded.
Now don’t get overwhelmed yet. This is a lot of information for one function, but require
is quite similar to other code-including functions and macros, so you’ll see the same patterns again.
Using other namespaces’ code as though it’s yours: use
Update (4/18/2012): As of the 1.4.0 release, there's no longer a good reason to use use
. Use require :refer
instead. From the Clojure 1.4.0 changelog: "require
can now take a :refer
option. :refer
takes a list of symbols to refer from the namespace or :all
to bring in all public vars."
Sometimes, including any namespace information at all seems too verbose (unit tests for a namespace are a good example). In these cases, we want to refer to vars
as though they were ours, and that’s where use
comes in.
Use
actually uses two other functions to do the bulk of its work: require
and refer
. We’ve covered require
already, and you’ll rarely have a need to use refer
directly, so let’s stick to the syntax of use
.
This is pretty heavy handed. We’ve just blown away the definitions of replace
and reverse
in clojure.core
, so if we wanted to use those again, we’d have to fully qualify those functions (something like clojure.core/replace
.
In addition, this kind of wholesale inclusion of vars
into our current namespace can make it difficult do decipher where the definitions live. It’s not something we want to do very often—maybe in the case of a unit test. It would be much better to limit the vars
being referred to a named subset, like this:
It still works, but now we’re very clear about what we want. Anyone peeking into this code for the first time will know immediately that split
comes from the clojure.string
namespace, with no need to grep
the whole project for the function definition.
Note that the libspecs here are strikingly similar to what we used for require
! We have a new option, :only
, where we used :as
before, and that option is associated with a list rather than a symbol, but it’s easy to see that they’re really the same sort of data structure.
There are other options with use
as well:
This eliminates one of the problems with the first use
example (shadowing the clojure.core
functions), but it’s still not obvious at a glance where split
comes from. I prefer :only
in most situations.
I’ve seen a quote come across my Twitter stream, attributed to Stuart Halloway (also discussed in the context of Fortran), that recommends: “Only use use
with :only.” With rare exceptions, I think that advice is pretty sound.
There’s one more available option, :rename
, that lets us specify a map of vars to rename in the context of the current namespace:
The most common of these options in the wild is certainly :only
, but knowing that all of these are available will prepare you for that moment when they’re exactly what you need.
It’s also worth pointing out here that you can also use :as
, in the same way that we did with require
, to provide a shorter alias for a namespace:
So it turns out that we could use use
for exactly the same purposes as require
, if we supply an empty list to the :only
option. I don’t recommend that use, as require
itself is more idiomatic, but it’s there!
Working with Java and deftypes/defrecords: import
In terms of syntax, import
is much simpler than either require
or use
as there are no options to specify various behaviors.
In general, you can think of import
as the way you get ahold of Java code. The specifics are only a bit more complex. Let’s take a look.
As long as the Java class you want is on the classpath, you can already refer to it using the fully qualified name:
If you’re at all familiar with Java already, you already know that import
can be used in a way similar to use
, so that you can just talk about a Date
in your code, rather than specifying the packages every time as java.util.Date
:
You’re probably already wondering if you can use a libspec instead of a plain old symbol! It’s actually not a libspec in this case, but you can indeed get some different behavior here by using a quoted list, similarly to the shared prefix example for require
:
So here we’re specifying a package as the first element of the vector, and the classes from that package that we want to import as the remaining elements.
You actually don’t need a vector here (a list would do just fine), but it seems more symmetrical to the other functions to use a vector, so that’s what I prefer here. I haven’t seen a strong trend emerge here, but particular projects generally stick to one or the other.
It’s very important to note here that import
actually applies to any classes you need to get ahold of, including Clojure defrecords
and deftypes
. Pretend you have a namespace stuff
which contains a defrecord
called BigWidget
.
One important detail here is that the initial require
is necessary—without it, you’ll get a ClassNotFoundException
. Defypes
work identically, though their printed representation will of course vary. You can use the same vector notation as with Java classes, but here you’d specify a namespace rather than a Java package as the first element of the vector.
This difference in code loading requirements between deftypes/defrecords
and other Clojure code may be surprising at first (it was to me, anyway), but the capitalization (along with several semantic differences) is a good hint that something different needs to happen.
And once you’ve require
d the Clojure namespace, you can refer to defrecords
and deftypes
by their fully qualified names (e.g. stuff.BigWidget
), in a similar way that you could with Java classes.
Bringing it all together: ns
While require
, use
, and import
are the basis for all of your expeditions into other people’s code in Clojure, you won’t often be using them directly in your actual Clojure projects.
It’s far more idiomatic to use the ns
macro, which pulls all of these together. The most basic use of ns
gives just the namespace for the code that comes afterwards—you’ll see at least this much in just about every Clojure file you come across:
Because we have so much background already, let’s jump right into a much more complex ns
example:
There’s a lot here to look at, but take heart! Our trusty old use
has been reincarnated as :use
, the first element of a list within the ns
macro body.
The same goes for require → :require
and import → :import
. The other syntax change to get used to is that we no longer need to quote any of our libspecs—that’s done internally. If you know much about how writing Clojure macros works, it’ll make a good bit of sense.
You can take any of our previous examples and plug them into the ns
macro with only these small changes. Multiple :use
, :require
, or :import
forms are okay here:
But it’s more often the case that you’d eliminate the duplication there by rolling those into the same :require
form:
Another point of style: unless you’re using the prefix form as in (clojure template walk)
from the first ns
example above, you generally want to stick to one namespace per line, and left align the libspecs.
Once you’ve made these small syntax leaps, you’ve got all the knowledge you’ll need to use Clojure libs. Remember that you should prefer ns
in any non-repl code that you write—the basic require
, use
, and import
are just the building blocks.
Libs can be among the most confusing areas of Clojure, but with a little effort and practice, they start to make a lot more sense. I hope this has been helpful—happy requiring!