3

I'm new in Clojure and i read that it is a functional language. It says that Clojure doesn't have variables, still when i find (def n 5), what's the difference between it and a variable?

I can change the value of the var after, so is it really that different from a variable? I don't understand the difference.

Asdren
  • 89
  • 4

4 Answers4

5

Assuming that by variable you mean a refer to a mutable storage location, I guess the main difference(depending against which language you compare) is that if you dynamically rebind the var in Clojure is on a per-thread basis.

But the long answer is that you don't usually use a var in Clojure unless you really need a reference to a mutable storage location.

Clojure favors immutability and programming using values instead of references.

You can watch Rich Hickey's talk about values.

A summary would be, when you're programming in Clojure what you have are values , not references to locations that may change (maybe even changed by another thread).

So.

(let [a 1 
      _ (println a) => prints 1
      a 2 
      _ (println a) => prints 2
     ]) 

Even if you get the illusion of "changing a" in that code, you're not changing the "old" a you just have a new value. (if someone would have looked at the first definition it would still be seeing the value 1).

Actually you can see that sequence of assignments as a composed function calls where a is being replaced in scope, but not the same "variable" at all.

 ((fn [a]
    (println a) => prints 1
    ((fn [a]
        (println a) => prints 2
      ) 2) 1)

None the less, if you need to have a mutable storage with potentially many threads accessing that storage, Clojure gives you vars, atoms, refs, etc.

guilespi
  • 4,672
  • 1
  • 15
  • 24
2

It is not true that Clojure does not have variables, i. e. changeable references. They are however not used to store and look up during computations that can be modeled as pure mathematical functions.

The concept of immutability is that of dealing with concrete values instead of references that one or others can change. Just like 1 is a value that you can't change, in Clojure the vector [3 2] is value that you also can't change. E. g. if your algorithm is required to append 1 to that vector, it needs to create a new vector, leaving the old one intact, while in imperative languages you could just "change" the vector, breaking everything potentially relying on it. The takeaway of immutability is that you don't have to worry about that anymore and your code becomes less error prone.

Clojure implements immutable datastructures in a way that such newly created values efficiently reuse most memory of the values they are based on. They provide near the same performance characteristics as their mutable counterparts both for reading and writing (i. e. creating new versions). You may want to read more about that here and Rich Hickey does some excellent explaining in this conversation with Brian Beckmann.

Leon Grapenthin
  • 9,246
  • 24
  • 37
0

Think about def as defining constant. It can be change by calling def again but you should not do it.

The closes thing to variables are agents which are thread safe.

(def counter (agent 0))
(send counter inc)
@counter
;;=> 1

You can also access the variable in Java class.

New class

(def object (ClassName.))

Se value

(.fieldName object)

Set value

(set! (.fieldName object) 5)

The "whole" point of of not having variables is to make program automatically thread safe. It is because thread error will "always" fail on that thread 1 wil tell the variable a is 1 and thread b tells that a is 2 and after that something fail. This is also reason to use pure functions - no variables "no" thread problem.

See also this question:Clojure differences between Ref, Var, Agent, Atom, with examples and this one Clojure: vars, atoms, and refs (oh my).

Treat "" as in 80% or more - not 100%.

Community
  • 1
  • 1
boucekv
  • 1,220
  • 2
  • 20
  • 47
0

In most programming languages the idea of a variable is a "name" and a "location" that can contain a "value". So, for example, in Python x = 4 creates a name "x" and a location associated or connected to "x" that contains a value "4". If we later say x = 5, "x" is the same name, connected to the same location, but the value is now "5".

Clojure gives the programmer control over names, locations, and how the locations are changed a-la-carte. To get the same behavior one would say in Clojure (def x (atom 4)). The def creates the name "x", the location is created by atom and the value in the atom is created by the literal 4. To change the value in Clojure one would evaluate (reset! x 5). This says find the atom/location with the name "x" and put the value "5" in it.

John Conti
  • 11
  • 4