Read: the Clojure reader reads the textual representation of code, producing the data structures (e.g., lists, vectors, and so on) and atomic values (e.g., symbols, numbers, strings, etc.) indicated in that code.
Evaluate: many of the values emitted by the reader evaluate to themselves (including most data structures and scalars like strings and keywords). We explored earlier in Expressions, Operators, Syntax, and Precedence how lists evaluate to calls to the operator in function position.
The only thing left to understand about evaluation now is how symbols are evaluated. So far, we’ve used them to both name and refer to functions, locals, and so on. Outside of identifying locals, the semantics of symbol evaluation are tied up with namespaces, Clojure’s fundamental unit of code modularity.
All Clojure code is defined and evaluated within a namespace. Namespaces are roughly analogous to modules in Ruby or Python, or packages in Java. Fundamentally, they are dynamic mappings between symbols and either vars or imported Java classes.
One of Clojure’s reference types, vars are mutable storage locations that can hold any value. Within the namespace where they are defined, vars are associated with a symbol that other code can use to look up the var, and therefore the value it holds.
Vars are defined in Clojure using the
def special form, which only ever acts within
the current namespace. Let’s define a var now in the
user namespace, named
x; the name of the var is the symbol that it is
keyed under within the current namespace:
(def x 1) ;= #'user/x
We can access the var’s value using that symbol:
x ;= 1
x here is
unqualified, so is resolved within the current
namespace. We can also redefine vars; this is critical for supporting
interactive development at the REPL:
(def x "hello") ;= #'user/x x ;= "hello"
Vars should only ever be defined in an interactive
context—such as a REPL—or within a Clojure source file as a way of
defining named functions, other constant values, and the like. In
particular, top-level vars (that is, globally accessible vars mapped
within namespaces, as defined by
and its variants) should only ever be defined by top-level expressions,
never in the bodies of functions in the normal course of operation of a
See Vars Are Not Variables for further elaboration.
Symbols may also be namespace-qualified, in which case they are resolved within the specified namespace instead of the current one:
*ns* ;= #<Namespace user> (ns foo) ;= nil *ns* ;= #<Namespace foo> user/x ;= "hello" x ;= #<CompilerException java.lang.RuntimeException: ;= Unable to resolve symbol: x in this context, compiling:(NO_SOURCE_PATH:0)>
Here we created a new namespace using the
ns macro (which has the side effect of switching
us to that new namespace in our REPL), and then referred to the value of
x in the
user namespace by using the namespace-qualified
user/x. Since we only just
created this new namespace
doesn’t have a mapping for the
symbol, so attempting to resolve it fails.
You need to know how to create, define, organize, and manipulate namespaces in order to use Clojure effectively. There is a whole suite of functions for this; please refer to Defining and Using Namespaces for our guidelines in their use.
We mentioned earlier that namespaces also map between symbols and
imported Java classes. All classes in the
java.lang package are imported by default into
each Clojure namespace, and so can be referred to without package
qualification; to refer to un-imported classes, a package-qualified symbol
must be used. Any symbol that names a class evaluates to that
String ;= java.lang.String Integer ;= java.lang.Integer java.util.List ;= java.util.List java.net.Socket ;= java.net.Socket
In addition, namespaces by default alias all of the vars defined in the primary namespace of
Clojure’s standard library,
clojure.core. For example, there is a
filter function defined in
clojure.core, which we can access without
namespace-qualifying our reference to it:
filter ;= #<core$filter clojure.core$filter@7444f787>
These are just the barest basics of how Clojure namespaces work; learn more about them and how they should be used to help you structure your projects in Defining and Using Namespaces.
 In fact, namespaces correspond precisely with Java packages when
types defined in Clojure are compiled down to Java classes. For
Person type defined in
the Clojure namespace
will produce a Java class named
app.entities.Person. See more about defining
types and records in Clojure in Chapter 6.
 Remember that the Clojure REPL session always starts in the