A namespace is a mapping from simple symbols to vars and classes. A var is a named, mutable storage location that can be rebound per thread. The two are how Clojure organises code: a file defines one namespace and a program is a set of them.
Namespaces
Vars are interned in a namespace by def and its variants (defn, defmacro, defonce …); the namespace then maps the var's symbol to it. A namespace can also map symbols to vars interned elsewhere (by refer or use) and to Java classes (by import, and by default the classes of java.lang and clojure.lang.Compiler). *ns* is the current namespace; it should be set only with ns or in-ns, which create the namespace if it does not exist.
- The
nsmacro creates a namespace that maps the classes ofjava.langand the functions ofclojure.core(unless:refer-clojuresays otherwise). - At the REPL,
in-nscreates a namespace that maps only thejava.langclasses;(clojure.core/refer 'clojure.core)brings in core. Theusernamespace has already done this.
The ns form
(ns name docstring? attr-map? references*) sets *ns* to the namespace, creating it. The documentation string and the attribute map become metadata of the namespace. Each reference is a list that begins with a keyword; its arguments are unevaluated and need no quote.
| Clause | Same as | Meaning |
|---|---|---|
(:require libspec*) | require | load libs, and optionally alias or refer from them |
(:use libspec*) | use | require plus refer of the lib's public vars |
(:import spec*) | import | make Java classes usable by their short name |
(:refer-clojure filter*) | refer-clojure | filter what is taken from clojure.core: :exclude, :only, :rename |
(:load path*) | load | load other resources of the lib |
(:gen-class option*) | gen-class | generate a Java class for the namespace when compiled ahead of time; defaults to :name the namespace name, :main true, :impl-ns the same namespace; ignored when not compiling |
The clause (:require-macros …) and the options :include-macros and :refer-macros belong to ClojureScript (see ClojureScript and .cljc).
(ns foo.bar
"Documentation of the namespace."
(:refer-clojure :exclude [ancestors printf])
(:require (clojure.contrib sql combinatorics)
[clojure.string :as str :refer [join]])
(:use (my.lib this that))
(:import (java.util Date Timer Random)
(java.sql Connection Statement)))
ns, with one libspec added.require, use, refer
require loads libs, skipping any already loaded. Each argument is a libspec (a lib name, or a vector with a lib name followed by options), a prefix list, or a flag.
| Option or flag | Where | Effect |
|---|---|---|
:as sym | libspec | makes sym an alias of the lib's namespace in this namespace |
:as-alias sym | libspec (since 1.11) | aliases like :as but does not load the lib; if it is not loaded, an empty namespace is created. Used for auto-resolved keywords such as ::sym/key |
:refer [a b] or :refer :all | libspec | refers the listed public vars, or all of them |
:exclude, :only, :rename | use libspec, refer | filters: a list to leave out; a list to take; a map of old name to new name |
:reload, :reload-all, :verbose | flag | load again even if loaded; also reload every lib they load; print each load, alias and refer |
A prefix list is a list of a shared prefix followed by libspecs with the prefix taken off (the remaining names must contain no periods): (require '(clojure zip [set :as s])) loads clojure.zip and clojure.set as s. use is require plus refer, and takes the filter options in libspecs.
(import spec*) takes a fully qualified class name, or a list or vector of a package followed by short class names: (import 'java.util.Date '(java.util List Map)). alias adds a namespace alias by hand: (alias 'str 'clojure.string).
Related functions
| For | Names |
|---|---|
| create or enter | ns in-ns create-ns |
| add to a namespace | def alias import intern refer refer-clojure |
| find | all-ns find-ns the-ns loaded-libs |
| examine | ns-name ns-aliases ns-imports ns-interns ns-map ns-publics ns-refers |
| resolve a symbol | resolve ns-resolve requiring-resolve namespace find-var |
| remove | ns-unalias ns-unmap remove-ns |
Vars
A var holds a value. (def x) creates an unbound var; (def x 1) sets its root binding (even if one exists). Vars are static by default; marking one ^:dynamic lets binding give it thread-local values that unwind in stack order. Bindings made by binding are seen only by the thread that made them, can be assigned with set!, and are conveyed by future and the agent functions to the threads they start.
(def ^:dynamic x 1)
(def ^:dynamic y 1)
(+ x y) ; => 2
(binding [x 2 y 3]
(+ x y)) ; => 5
(+ x y) ; => 2
Functions defined with defn live in vars, so they can be redefined in a running program. (var x) or #'x returns the var object, which is how a macro or a callback can be redefined later. with-local-vars makes vars that are not interned (symbol resolution never finds them; read them with var-get and set them with var-set). A validator (set-validator!) can reject new values. set! assigns the thread-local binding of a dynamic var; it is an error to set the root with it. Locals and function parameters cannot be assigned at all.
Var metadata
| Key | Meaning |
|---|---|
:doc | the documentation string |
:added | the version in which the var was added |
:private | an implementation detail: not referred and not listed by the ns- functions that list public vars (but still reachable by #'ns/name) |
:arglists | a list of parameter vectors; made by defn and written by hand for macros |
:macro | true for a macro, set by defmacro |
:tag | the class of the value, or of the return value of a function. Var metadata is evaluated, so ^long on a var is the long function and not a primitive hint; the reference prefers a type hint on the argument list of a defn |
:test | a test function (used by clojure.test) |
:dynamic | may be rebound in a thread; dynamic vars are not direct-linked |
:redef | should not be direct-linked, so it can be redefined |
:const | a compile-time constant that the compiler may inline (read but not evaluated values: numbers, strings and the like) |
:static | no longer used |
:file :line :column :name :ns | put on by the compiler |
Vars are one of four reference types, with refs, agents and atoms.
Documentation strings
A string in the documentation position of def, defn, defmacro, defmulti, defprotocol (and each of its methods), ns and similar forms sets :doc. clojure.repl/doc prints it with the arglists, find-doc and apropos search, source prints the source.
Not described
Known, not yet covered
- Reference: the full option set of
gen-classandgen-interface(:extends,:implements,:constructors,:methods,:state,:init,:prefixand more) is not tabulated; the sourcegenclass.cljwas downloaded but not read in full. - Reference:
*loaded-libs*internals,:reloadsemantics for namespaces with circular loading and theclojure.tools.namespacelibrary are not covered.
Unknown
- Reference: the claim that a private var stays reachable by
#'ns/nameis from knowledge of the language; the reference page on vars says only that private vars are not referred or listed.
See also
- File structure – how namespaces map to paths
- Common Lisp: symbols and packages – the Common Lisp counterpart