Clojure Does Not Have Variables


Clojure, like many functional languages, does not have "variables". It has "bindings", but they cannot vary - there is no concept of reassignment. But what does that really mean?

When you see code like this:

(let [x (something)
      y (blah x)
      x (more (stuff x) y)]
  (whatever x))

you may very well think "you are re-binding x - that's the same thing as a variable, for all intents and purposes". And I agree that it looks that way. But it's not.

Here's the difference:

# python
def foo():
  x = 23
  y = lambda: x
  x = 44
  return y

print foo()()
# ruby
def foo():
  x = 23
  y = lambda { x }
  x = 44
  y

puts foo.call
// javascript
var foo = function(){
  var x = 23;
  var y = function(){ return x; }
  x = 44;
  return y;
};

alert( foo()() );
; clojure
(defn foo []
  (let [x 23
        y (fn [] x)
        x 44]
    y))

(println ((foo)))

One of these things is not like the others... one of these things is not the same. (I can't remember which childhood TV show that's from).

Three of the snippets above print 44. The other prints 23. That may not seem very significant, but it is. Immutability runs deeper than just unmodifiable vectors and maps.