A namespace groups related functions, vars, and other things. Without namespaces, different functions with the same names would interfere and cause problems. Even in a REPL, you always work within a namespace.

The repl prompt below is probably familiar to you already.

user=>

What is this user? This is the default namespace when you start the repl.

user=> *ns*
#<Namespace user>

user=> (doc *ns*)
-------------------------
clojure.core/*ns*
  A clojure.lang.Namespace object representing the current namespace.
nil

Let’s create a new namespace. You can do this in three ways:

user=> ; below creates a new namespace if necessary and stays on the current namespace

user=> (create-ns 'my.first.ns)
#<Namespace my.first.ns>

user=> ; below creates a new namespace if necessary and moves on to the given namespace

user=> (in-ns 'my.second.ns)
#<Namespace my.second.ns>

my.second.ns=> ; below is the same as in-ns, plus, loads clojure.core

my.second.ns=> (ns my.third.ns)
nil
my.third.ns=> (ns user) ; back to user namespace
nil
user=>
  • Advice to coaches

    Please explain the differences of the three functions, perhaps by using the doc function. If the namespace has been changed by in-ns, you can call the doc function using its namespace. For example: (clojure.repl/doc clojure.core/in-ns).


You can confirm that var names are different in each namespace.

user=> (def abc 123)  ; creates a var, #'user/abc
#'user/abc
user=> (ns-map 'user)  ; looks up user namespace var mapping
{sorted-map #'clojure.core/sorted-map, read-line #'clojure.core/read-line, re-pattern #'clojure.core/re-pattern, cond->> #'clojure.core/cond->>, keyword? #'clojure.core/keyword?, (... a bunch, snip)

user=> ('abc (ns-map *ns*))  ; finds a value giving a key, abc
#'user/abc
user=> ; #'user/abc is there

user=> (ns my.third.ns)
nil
my.third.ns=> (def abc 456) ; creates a var, #my.third.ns/abc
#'my.third.ns/abc

my.third.ns=> ('abc (ns-map *ns*)) ; checks #'my.third.ns/abc is there
#'my.third.ns/abc

my.third.ns=> abc
456
my.third.ns=> user/abc
123

So far, we have learned how to create a namespace. The next step is to use namespaces. You will do this very often because almost all Clojure programs use some or many libraries. Every library groups functions into its own namespace.

To explore namespaces, we want to set up at least two different namespaces and different functions in those namespaces.

Create a Clojure project and write two Clojure files, one.clj and two.clj.

$ lein new my-nses

Both one.clj and two.clj should be in the my-nses/src/my_nses directory.

my-nses/src
└── my_nses
    ├── one.clj
    └── two.clj

Once the code is ready, start repl in the my-nses (top) directory. To use our code, we have two choices: use or require. For the first attempt, we will use the use function.

user=> (use 'my-nses.one)
nil
user=> (greet)
Good-Bye!
nil
user=> (greet "Clojure")
Welcome!  Clojure
nil
user=> (area 4 6)
12.0
user=> ; it looks like it's working, yay!

user=> (use 'my-nses.two)

IllegalStateException area already refers to: #'my-nses.one/area in namespace: user  clojure.lang.Namespace.warnOrFailOnReplace (Namespace.java:88)
user=> ; oh no!

user=> ; it's ok. we can narrow down functions to use

user=> (use '[my-nses.two :only [greeting]])
nil
user=> (greeting "Clojure")
Hello!  Clojure
nil
user=> ; but how can we use the area function in my-nses.two namespace ?

As we tried, use function loads the functions of the specified namespace(s) into current namespace. If you have a duplicate function, that will result in an exception.

In the next attempt, we will use the require function. This resolves the error that happened above.

user=> (require 'my-nses.two)
nil
user=> (my-nses.two/area 1 1)
4
user=> ; but every time, we need to type, m, y, -, n, s, e, s, ., t, w, o ?

user=> ; no, we can set up a shortcut

user=> (require '[my-nses.two :as two])
nil
user=> (two/area 2 0)
6
user=> (two/area 2 1)
7
user=> ; we can still use functions in my-nses.one namespace

user=> (area 2 1)
1.0

We tried just some of the namespace management functions. Clojure has more ways to avoid function name collision. If you’re not using a repl, requiring or using other namespaces is slightly different.

Please see references for details:

References

These are useful references, especially, the first is worth reading.