liveBook · Manning

Clojure var

As explained in Clojure: The Essential Reference

A Clojure var is a named mutable reference that stores a root binding and associated metadata within a namespace.

A Clojure var is a named reference to a value. A namespace maps symbols to objects, including vars; `def` and `intern` add entries to that mapping. A var can have a root binding visible to all threads, while a thread-local binding lets a thread see its own value. section 16.0

Retrieve the var, not just its value

After `(def a 1)`, `(var a)` returns `#'user/a`. The reader syntax `#'a` is equivalent to `(var a)`. By contrast, `(var missing)` throws an unresolved-var exception: retrieval does not create a var or namespace. section 16.2

Choose a lookup operation to match what you know and how you want absence handled:

  • `var` retrieves a var associated with a symbol in the current or another namespace; it throws if none is found. section 16.2
  • `find-var` requires a namespace-qualified symbol and returns `nil` when the var is absent. section 16.2
  • `resolve` searches from the current namespace; `ns-resolve` accepts a namespace to search. These can also resolve Java classes. section 16.2

A function defined with `defn` is referenced by the var that `defn` returns. That var also stores metadata such as its docstring and definition tags. Inspect it with `(meta #'hello)`; `(:doc (meta #'hello))` retrieves a docstring. Metadata can guide operations on selected vars: a `:bench` tag, for example, can identify functions whose roots should be wrapped with `alter-var-root` for timing. section 2.1.1

(def ^:dynamic *dvar*) ; #1

((ns-map 'user) '*dvar*)
;; #'user/*dvar1*

(bound? #'*dvar*)
;; false

(thread-bound? #'*dvar*)
;; false

(binding [*dvar* 1] ; #2
  [(bound? #'*dvar*)
   (thread-bound? #'*dvar*)])
;; [true true]

(def avar) ; #3

(bound? #'avar)
;; false

(thread-bound? #'avar)
;; false

(intern *ns* 'avar 1) ; #4
(bound? #'avar)
;; true

(thread-bound? #'avar)
;; false

Compare an unbound var, a thread-local binding established with `binding`, and a root value assigned with `intern`. `bound?` and `thread-bound?` distinguish the resulting states. section 16.2

How Clojure: The Essential Reference covers it

How deep it goes
Defines root and thread-local bindings and works through lookup, metadata, and binding checks without detailing Var class internals.
Examples
Shows `var` and `#'` lookup, failed resolution, metadata inspection, tagged profiling, and `bound?` versus `thread-bound?`.
What it assumes
Assumes familiarity with Clojure symbols and function definitions while defining namespaces, vars, and bindings explicitly.
What you can do after
Diagnose/debug with vars by retrieving definitions, checking binding state, and choosing lookup behavior for missing symbols.
How it connects
Connects vars to namespaces, symbols, function definitions, metadata, dynamic binding, and Java class resolution.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Clojure: The Essential Reference. The section links point to the parts of the book it draws on.