Clojure Libs and Namespaces: require, use, import, and ns

Clojure Libs and Namespaces: require, use, import, and ns

Colin Jones

December 05, 2010

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:

user=> (clojure.string/split "name,address,city,state,zip,email,phone" #",")
java.lang.ClassNotFoundException: clojure.string (NO_SOURCE_FILE:0)

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:

user=> (require 'clojure.string)
user=> (clojure.string/split "name,address,city,state,zip,email,phone" #",")
["name" "address" "city" "state" "zip" "email" "phone"]

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:

user=> (require 'clojure.string 'clojure.test)
user=> (clojure.string/join " " ["name" "address" "city" "state" "zip" "email" "phone"])
"name address city state zip email phone"
user=> (clojure.test/is (= 1 2))

FAIL in clojure.lang.PersistentList$EmptyList@1 (NO_SOURCE_FILE:10)
expected: (= 1 2)
	actual: (not (= 1 2))

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:

user=> (require '[clojure.string :as string])
user=> (string/capitalize "foo")

The strange looking quoted vector is a shorthand to avoid having to quote every individual symbol within the vector. You could type:

(require ['clojure.string :as 'string])

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:

user=> (require 'clojure.string '[clojure.test :as test])
user=> (test/is (= 1 1))

One last way to use require simplifies things when a prefix is the same in several libraries you want to load:

user=> (require '(clojure string test))

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:

user=> (require '(clojure [string :as string] test))
user=> (string/join [1 2 3])

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):

user=> (require '[clojure.string :as string] :verbose)
(clojure.core/load "/clojure/string")
(clojure.core/in-ns 'user)
(clojure.core/alias 'string '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:

user=> (require '[clojure.test :as test] :verbose)
(clojure.core/load "/clojure/test")
(clojure.core/load "/clojure/template")
(clojure.core/load "/clojure/walk")
(clojure.core/in-ns 'clojure.template)
(clojure.core/alias 'walk 'clojure.walk)
(clojure.core/in-ns 'clojure.test)
(clojure.core/alias 'temp 'clojure.template)
(clojure.core/load "/clojure/stacktrace")
(clojure.core/in-ns 'clojure.test)
(clojure.core/alias 'stack 'clojure.stacktrace)
(clojure.core/in-ns 'user)
(clojure.core/alias 'test 'clojure.test)

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:

user=> (require 'clojure.string :verbose)
(clojure.core/load "/clojure/string")
user=> (require 'clojure.string :verbose)

Nothing happens the second time, as you can see. However, we can change that with the :reload flag:

user=> (require 'clojure.string :verbose)
(clojure.core/load "/clojure/string")
user=> (require 'clojure.string :verbose :reload)
(clojure.core/load "/clojure/string")

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.

user=> (use 'clojure.string)
WARNING: replace already refers to: #'clojure.core/replace in namespace: user, being replaced by: #'clojure.string/replace
WARNING: reverse already refers to: #'clojure.core/reverse in namespace: user, being replaced by: #'clojure.string/reverse
user=> (split "a,b,c" #",")
["a" "b" "c"]

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:

user=> (use '[clojure.string :only [split]])
user=> (split "a,b,c" #",")
["a" "b" "c"]

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:

user=> (use '[clojure.string :exclude [replace reverse]])
user=> (split "a,b,c" #",")
["a" "b" "c"]

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:

user=> (use '[clojure.string :rename {replace str-replace, reverse str-reverse}])
user=> (str-reverse "foobar")
user=> (reverse "foobar")
(\r \a \b \o \o \f)

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:

user=> (use '[clojure.string :as str :only [join split]])
user=> (str/replace "foobar" "f" "p")

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:

user=> (java.util.Date.)
# 22 mon cst 20:34:52 2010 nov>

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:

user=> (import 'java.util.Date)
user=> (Date.)
# 22 mon cst 20:34:52 2010 nov>

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:

user=> (import '(java.util Date GregorianCalendar))
user=> Date
user=> GregorianCalendar

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.

user=> (require 'stuff)
user=> (import 'stuff.BigWidget)
user=> (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 required 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:

(ns my-great-project.core)

Because we have so much background already, let’s jump right into a much more complex ns example:

(ns my-great-project.core
		"This namespace is CRAZY!"
		(:use [clojure.string :only [split join]] :reload)
		(:require clojure.stacktrace
												[clojure.test :as test]
												(clojure template walk) :verbose)
		(:import (java.util Date GregorianCalendar)))

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:

(ns my-great-project.core
		(:require [clojure.stacktrace])
		(:require [clojure.walk]))

But it’s more often the case that you’d eliminate the duplication there by rolling those into the same :require form:

(ns my-great-project.core
		(:require [clojure.stacktrace]

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!