= Vars and the Global Environment
Rich Hickey
2016-01-14
:type: reference
:toc: macro
:icons: font
:navlinktext: Vars and Environments
:prevpagehref: libs
:prevpagetitle: Libs
:nextpagehref: refs
:nextpagetitle: Refs and Transactions

ifdef::env-github,env-browser[:outfilesuffix: .adoc]

toc::[]

Clojure is a practical language that recognizes the occasional need to maintain a persistent reference to a changing value and provides 4 distinct mechanisms for doing so in a controlled manner - Vars, <<refs#,Refs>>, <<agents#,Agents>> and <<atoms#,Atoms>>. Vars provide a mechanism to refer to a mutable storage location that can be dynamically rebound (to a new storage location) on a per-thread basis. Every Var can (but needn't) have a root binding, which is a binding that is shared by all threads that do not have a per-thread binding. Thus, the value of a Var is the value of its per-thread binding, or, if it is not bound in the thread requesting the value, the value of the root binding, if any.

The special form `def` creates (and <<vars#interning,interns>>) a Var. If the Var did not already exist and no initial value is supplied, the var is unbound:

[source,clojure]
----
user=> (def x)
#'user/x
user=> x
#object[clojure.lang.Var$Unbound 0x14008db3 "Unbound: #'user/x"]
----

Supplying an initial value binds the root (even if it was already bound).

[source,clojure]
----
user=> (def x 1)
#'user/x

user=> x
1
----

By default Vars are static, but Vars can be marked as dynamic to allow per-thread bindings via the macro https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/binding[binding]. Within each thread they obey a stack discipline:

[source,clojure]
----
user=> (def ^:dynamic x 1)
user=> (def ^:dynamic y 1)
user=> (+ x y)
2

user=> (binding [x 2 y 3]
         (+ x y))
5

user=> (+ x y)
2
----

Bindings created with `binding` cannot be seen by any other thread. Likewise, bindings created with `binding` can be assigned to, which provides a means for a nested context to communicate with code before it is placed on the call stack. This capability is opt-in only by setting a metadata tag: `^:dynamic` to true as in the code block above. There are scenarios that one might wish to redefine static Vars within a context and Clojure (since version 1.3) provides the functions https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/with-redefs[with-redefs] and https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/with-redefs-fn[with-redefs-fn] for such purposes.

Functions defined with https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/defn[defn] are stored in Vars, allowing for the re-definition of functions in a running program. This also enables many of the possibilities of aspect- or context-oriented programming. For instance, you could wrap a function with logging behavior only in certain call contexts or threads.

[[conveyance]]
== Binding conveyance

Some Clojure concurrency functions (futures, <<agents#,agents>>) provide "binding conveyance", which allows the current set of dynamic bindings to be conveyed to another thread for the purpose of continuing work asynchronously with the same environment. This functionality is provided by https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/future[future], https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/send[send], https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/send-off[send-off], and https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/pmap[pmap].

[source,clojure]
----
(def ^:dynamic *num* 1)
(binding [*num* 2] (future (println *num*)))
;; prints "2", not "1"
----

[[set]]
== (*set!* var-symbol expr)

Assignment special form.

When the first operand is a symbol, it must resolve to a global var. The value of the var's current thread binding is set to the value of expr. Currently, it is an error to attempt to set the root binding of a var using set!, i.e. var assignments are thread-local. In all cases the value of expr is returned.

Note - _you cannot assign to function params or local bindings. Only Java fields, Vars, Refs and Agents are mutable in Clojure_.

Using http://clojure.github.io/clojure/clojure.core-api.html#clojure.core/set![`set!`] for Java fields is documented in <<java_interop#set,Java Interop>>.

[[interning]]
== Interning

The Namespace system maintains global maps of symbols to Var objects _(see <<namespaces#,Namespaces>>)_. If a `def` expression does not find an interned entry in the current namespace for the symbol being def-ed, it creates one, otherwise it uses the existing Var. This find-or-create process is called interning. This means that, unless they have been unmap-ed, Var objects are stable references and need not be looked up every time. It also means that namespaces constitute a global environment in which, as described in <<evaluation#,Evaluation>>, the compiler attempts to resolve all free symbols as Vars.

The <<special_forms#var,var>> special form or the `pass:[#']` reader macro _(see <<reader#,Reader>>)_ can be used to get an interned Var object instead of its current value.

[[local-vars]]
== Non-interned Vars

It is possible to create vars that are not interned by using https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/with-local-vars[with-local-vars]. These vars will not be found during free symbol resolution, and their values have to be accessed manually. But they can serve as useful thread-local mutable cells.

[[metadata]]
== Var metadata

The forms that create vars `def`, `defn`, `defmacro`, etc use a standard set of var <<metadata#,metadata>> to describe vars. Some of these forms use explicit syntax to accept values stored in the metadata, but generally you can also supply that metadata as a map on the var symbol.

Common var metadata keys (all optional at var definition):

* `:doc` - a string documenting the var, usually set by the docstring parameter
* `:added` - a string documenting the version when this var was added
* `:private` - a boolean flag, often set by `defn-`, used by the author to state the intent that this var is an implementation detail. Private vars are globally accessible but will not be referred or listed in `ns-`... functions which filter to non-private vars.
* `:arglists` - a coll of arglists, will be generated automatically if not supplied, most often used to document macro syntax
* `:macro` - a boolean flag added by `defmacro` automatically (not typically used directly)
* `:tag` - a type identifier (usually a class) for the type of the value in the var or the return type of a function held in the var. Note that var metadata is evaluated, so type hints like `^long` on the var will evaluate to the `long` function, not a `long` primitive type hint. Generally, it is preferred to use a type hint on the arglist for defn vars instead.
* `:test` - the `clojure.test` framework attaches unit tests to vars using this key (not typically used directly)
* `:dynamic` - indicates a var may be dynamically rebound in a thread context (see above). Dynamic vars will not be direct linked when compiling with direct linking.
* `:redef` - indicates that a var should not be direct linked when compiling with direct linking (thus allowing it to be redefined)
* `:static` - no longer used (originally vars were dynamic by default, now they are static by default)
* `:const` - indicates that a var is a compile-time constant and the compiler can inline the value into code that uses it. Note: this is rarely needed and only works with constants at compile time (read, but not evaluated), such as numbers, strings, etc (NOT classes, functions, ref types, etc). Redefining or dynamically binding a const var will not affect code that consumes the var that has already been compiled and loaded in the runtime.

Also see <<compilation#_compiler_options,Compiler Options>> for more information about direct linking and metadata elision during compilation.

[[related]]
== Related functions

[%hardbreaks]
Variants of `def`: https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/defn[defn] https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/defn-[defn-] https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/definline[definline] https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/defmacro[defmacro] https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/defmethod[defmethod] https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/defmulti[defmulti] https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/defonce[defonce] https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/defstruct[defstruct]
Working with interned Vars: https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/declare[declare] https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/intern[intern] https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/binding[binding] https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/find-var[find-var] <<special_forms#var,var>>
Working with Var objects: https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/with-local-vars[with-local-vars] https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/var-get[var-get] https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/var-set[var-set] https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/alter-var-root[alter-var-root] https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/var?[var?] https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/with-redefs[with-redefs] https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/with-redefs-fn[with-redefs-fn]
Var validators: https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/set-validator![set-validator!] https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/get-validator[get-validator]
Using Var metadata: https://clojure.github.io/clojure/clojure.repl-api.html#clojure.repl/doc[doc] https://clojure.github.io/clojure/clojure.repl-api.html#clojure.repl/find-doc[find-doc] https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/test[test]
