Clojure Guides_ Language_ Namespaces
Clojure Guides_ Language_ Namespaces
This work is licensed under a Creative Commons Attribution 3.0 Unported License
(https://creativecommons.org/licenses/by/3.0/) (including images & stylesheets). The source is available
on Github (https://github.com/clojure-doc/clojure-doc.github.io).
Overview
Clojure functions are organized into namespaces. Clojure namespaces are similar to Java packages and
Python modules. Namespaces are like maps (dictionaries) that map names to vars. In many cases, those
vars store functions in them.
Defining a Namespace
Namespaces are usually defined using the clojure.core/ns macro. In its most basic form, it takes a
name as a symbol:
(ns superlib.core)
(ns megacorp.service.core)
It is highly recommended to avoid using single segment namespaces (e.g. (ns superlib) ) to avoid
potential conflicts with the way Java handles default packages. If a library or application belongs to an
organization or a group of projects, the [organization].[library|app].[group-of-functions]
pattern is recommended. For example:
(ns clojurewerkz.welle.kv)
(ns megacorp.search.indexer.core)
(:require ...)
(:import ...)
(:use ...)
(:refer-clojure ...)
(:gen-class ...)
(ns megacorp.profitd.scheduling
(:require clojure.set))
This will make sure the clojure.set namespace is loaded, compiled, and available as clojure.set
(using its fully qualified name). It is possible (and common) to make a namespace available under an
alias:
(ns megacorp.profitd.scheduling
(:require [clojure.set :as set]))
It is common to use the last segment of the namespace name as the alias, as long as this does not cause
a conflict with other namespaces that would have the same alias. Some namespaces have widely-used
aliases that do not follow this pattern (e.g., clojure.string is usually aliased as str ).
(ns megacorp.profitd.scheduling
(:require [clojure.set :as set]
[clojure.walk :as walk]))
When you :require / :as , the referenced namespace is loaded (and compiled) and therefore must
exist as a source namespace. If you are working with qualified keywords, such as Spec names, you may
want an alias to a qualified keyword that does not match a source namespace. :require / :as-alias
can be used in that case to introduce an alias for a qualified name, without attempting to load a
namespace.
(ns megacorp.profitd.example
(:require [megacorp.profitd.scheduling :as scheduling]
[megacorp.profitd :as-alias profitd]))
megacorp.profitd.scheduling must exist as a source namespace and will be loaded and compiled.
megacorp.profitd does not need to exist as a source namespace and no attempt will be made to load
it. You can then use ::profitd/data to refer to the qualified keyword :megacorp.profitd/data
without having to type the full name.
(ns megacorp.profitd.scheduling
(:require [clojure.set :refer [difference intersection]]))
The :refer feature of the :require form was added in Clojure 1.4.
(ns megacorp.profitd.scheduling
(:require [clojure.set :refer :all]))
It is recommended you avoid :refer :all and prefer an alias instead. Use :refer to make specific
functions available if it makes the code easier to read. A couple of good examples are:
(ns megacorp.profitd.scheduling
(:import java.util.concurrent.Executors))
This will make sure the java.util.concurrent.Executors class is imported and can be used by its
short name, Executors . It is possible to import multiple classes:
(ns megacorp.profitd.scheduling
(:import java.util.concurrent.Executors
java.util.concurrent.TimeUnit
java.util.Date))
If multiple imported classes are in the same namespace (like in the example above), it is possible to avoid
some duplication by using an import list. The first element of an import list is the package and other
elements are class names in that package:
(ns megacorp.profitd.scheduling
(:import [java.util.concurrent Executors TimeUnit]
java.util.Date))
Even though import list is called a list, it can be a vector as shown here. Some people prefer to use lists
for import lists, on the grounds that the first element is special: it's a package name and subsequent
elements are class names.
This means that in the megacorp.profitd.scheduling namespace, find already refers to a value
which happens to be clojure.core/find , but it is being replaced by a different value. Remember,
Clojure is a very dynamic language and namespaces are basically maps, as far as the implementation
goes. Most of the time, however, replacing vars like this is not intentional and Clojure compiler emits a
warning.
To address this warning, you can either rename your function, or else exclude certain clojure.core
functions from being referred using the (:refer-clojure ...) form within the ns :
(ns megacorp.profitd.scheduling
(:refer-clojure :exclude [find]))
(defn find
"Finds a needle in the haystack."
[^String haystack]
(comment ...))
In this case, to use clojure.core/find , you will have to use its fully qualified name:
clojure.core/find :
(ns megacorp.profitd.scheduling
(:refer-clojure :exclude [find]))
(defn find
"Finds a needle in the haystack."
[^String haystack]
(clojure.core/find haystack :needle))
(ns megacorp.profitd.scheduling
(:refer-clojure :exclude [find])
(:require [clojure.core :as core]))
(defn find
"Finds a needle in the haystack."
[^String haystack]
(core/find haystack :needle))
cc is also a common alias used for clojure.core so it is less likely to conflict with a core alias from
another namespace:
(ns megacorp.profitd.scheduling
(:refer-clojure :exclude [find])
(:require [clojure.core :as cc]))
(defn find
"Finds a needle in the haystack."
[^String haystack]
(cc/find haystack :needle))
(ns megacorp.profitd.scheduling-test
(:use clojure.test))
In the example above, all functions in clojure.test are made available in the current namespace. This
practice (known as "naked use") works for clojure.test in test namespaces, but in general not a good
idea. (:use ...) supports limiting functions that will be referred:
(ns megacorp.profitd.scheduling-test
(:use clojure.test :only [deftest testing is]))
It is highly recommended to use (:require ...) (optionally with ... :refer [...] ) in modern
Clojure code. (:use ...) is a thing of the past and now that (:require ...) with :refer is capable
of doing the same thing when you need it, it is a good idea to let (:use ...) go.
(ns superlib.core
"Core functionality of Superlib.
Metadata can contain any additional keys such as :author which may be of use to various tools (such
as Codox (https://clojars.org/codox) or cljdoc.org (https://cljdoc.org)).
clojure.core/use does the same thing as clojure.core/require but with the :refer option (as
discussed above). It is not generally recommended to use use with Clojure versions starting with 1.4.
Use clojure.core/require with :refer instead.
A namespace can contain vars or be used purely to extend protocols, add multimethod implementations,
or conditionally load other libraries (e.g. the most suitable JSON parser or key/value store
implementation). In all cases, to trigger compilation, you need to require the namespace.
Private Vars
Vars (and, in turn, functions defined with defn ) can be private. There are two equivalent ways to specify
that a function is private: either via metadata or by using the defn- macro:
(ns megacorp.superlib)
;;
;; Implementation
;;
(defn- data-stream
[source]
(comment ...))
How to Look up and Invoke a Function by Name
It is possible to look up a function in a particular namespace by-name with clojure.core/ns-resolve .
This takes quoted names of the namespace and function. The returned value can be used just like any
other function, for example, passed as an argument to a higher order function:
The namespace must have already been loaded and compiled. If it has not, ns-resolve will throw an
exception.
Unlike ns-resolve , if the namespace has not already been loaded and compiled, resolve will return
nil instead of throwing an exception.
If you want to resolve a symbol in a namespace that has not yet been loaded and compiled, use
requiring-resolve :
Compiler Exceptions
This section describes some common compilation errors.
ClassNotFoundException
This exception means that JVM could not load a class. It is either misspelled or not on the classpath
(/articles/language/glossary/#classpath). Potentially your project has an unsatisfied dependency.
Example:
user=> (import java.uyil.concurrent.TimeUnit)
Execution error (ClassNotFoundException) at java.net.URLClassLoader/findClass (UR
java.uyil.concurrent.TimeUnit
Note that import is a macro so the package and class names do not need to be quoted (unlike
require which is a function and evaluates its arguments first).
Wrapping Up
Namespaces are basically maps (dictionaries) that map names to vars. In many cases, those vars store
functions in them.
This implementation lets Clojure have many of its highly dynamic features at a very reasonable runtime
overhead cost. For example, vars in namespaces can be temporarily altered for unit testing purposes.
Contributors
Michael Klishin [email protected] (mailto:[email protected]) (original author)
Links
About (/articles/about/)
Table of Contents (/articles/content/)
Getting Started (/articles/tutorials/getting_started/)
Introduction to Clojure (/articles/tutorials/introduction/)
Clojure Editors (/articles/tutorials/editors/)
Clojure Community (/articles/ecosystem/community/)
Basic Web Development (/articles/tutorials/basic_web_development/)
Language: Functions (/articles/language/functions/)
Language: clojure.core (/articles/language/core_overview/)
Language: Collections and Sequences (/articles/language/collections_and_sequences/)
Language: Namespaces
Language: Java Interop (/articles/language/interop/)
Language: Polymorphism (/articles/language/polymorphism/)
Language: Concurrency and Parallelism (/articles/language/concurrency_and_parallelism/)
Language: Macros (/articles/language/macros/)
Language: Laziness (/articles/language/laziness/)
Language: Glossary (/articles/language/glossary/)
Ecosystem: Library Development and Distribution (/articles/ecosystem/libraries_authoring/)
Ecosystem: Web Development (/articles/ecosystem/web_development/)
Ecosystem: Generating Documentation (/articles/ecosystem/generating_documentation/)
Building Projects: tools.build and the Clojure CLI (/articles/cookbooks/cli_build_projects/)
Data Structures (/articles/cookbooks/data_structures/)
Strings (/articles/cookbooks/strings/)
Mathematics with Clojure (/articles/cookbooks/math/)
Date and Time (/articles/cookbooks/date_and_time/)
Working with Files and Directories in Clojure (/articles/cookbooks/files_and_directories/)
Middleware in Clojure (/articles/cookbooks/middleware/)
Parsing XML in Clojure (/articles/cookbooks/parsing_xml_with_zippers/)
Growing a DSL with Clojure (/articles/cookbooks/growing_a_dsl_with_clojure/)