The story of Clojure Var's - part 1

May 13, 2010

A `Var' is something that you create using `def':

(def k 10)
(def k 20)
(def m 3)

We might think of a var as some kind of a `variable' in a traditional programming language. But there are several things to keep in mind when using a var. Let's look at some code snippets and try to understand the working of vars.

(def k 20)
(defn foo [] (println k))

(foo) ; prints 20

`foo' prints 20 when called; it feels as if `k' is some kind of a `global' variable.

(def k 20)
(defn foo [] (def k 30))
(+ k 1) ; prints 31

Note that the `def' within the body of `foo' is changing our `global' k. If you are a Python programmer and think of `def' as being some kind of assignment operator, the above code snippet is going to create confusion. Let's translate the above code to Python:

k = 20
def foo():
   k = 30
print k # prints 20

The solution is to think of `def' as being NOT equal to assignment; `def' has its own semantics which we have to understand without any kind of unconscious association with other programming languages.

Before trying out the following code snippet, make sure that you have not def'd anything called `m'.

(defn foo [] (def m 100))
(+ m 1) ; prints 101

The `def' within `foo' doesn't create any kind of `local' variable called `m'; instead it creates a `var' `m' in global scope.

The confusion increases when we bring function parameters into the picture:

(def m 10)
(defn foo [m] (def m 20) (+ m 1))
(foo m) ; returns 11
(+ m 1) ; prints 21

This is the idea: function parameters are not "variables" - they can't be altered. When you call `(foo m)', the parameter `m' gets the value 10 and that's it - it can't be changed!

When you do `(def m 20)' within the function, you are NOT modifying the parameter `m' but changing the value of the globally defined `m'. The expression `(+ m 1)' returns 11 because the symbol `m' within function `foo' always refers to the function parameter whenever it is NOT in the context of a `def'.

This is not the end of the story of `vars' - stay tuned for the next part were we look at `thread local bindings' and dynamic scoping with vars!

[Go to Code Clojure home] [Follow me on Twitter] [Go to home]