I know I can do the following in Common Lisp:
CL-USER> (let ((my-list nil))
(dotimes (i 5)
(setf my-list (cons i my-list)))
my-list)
(4 3 2 1 0)
How do I do this in Clojure? In particular, how do I do this without having a setf in Clojure?
Clojure bans mutation of local variables for the sake of thread safety, but it is still possible to write loops even without mutation. In each run of the loop you want to
my-list
to have a different value, but this can be achieved with recursion as well:Clojure also has a way to "just do the looping" without making a new function, namely
loop
. It looks like alet
, but you can also jump to beginning of its body, update the bindings, and run the body again withrecur
."Updating" parameters with a recursive tail call can look very similar to mutating a variable but there is one important difference: when you type
my-list
in your Clojure code, its meaning will always always the value ofmy-list
. If a nested function closes overmy-list
and the loop continues to the next iteration, the nested function will always see the value thatmy-list
had when the nested function was created. A local variable can always be replaced with its value, and the variable you have after making a recursive call is in a sense a different variable.(The Clojure compiler performs an optimization so that no extra space is needed for this "new variable": When a variable needs to be remembered its value is copied and when
recur
is called the old variable is reused.)