Just like in Lisp, Clojure uses
let to define locals. The only real difference is that Clojure uses a vector of names and their bindings, whereas Lisp uses a nested list.
This Lisp code
(let ((a 5) (b 6)) (+ a b))
looks like this in Clojure
(let [a 5 b 6] (+ a b))
I think the Clojure way is a little easier to read.
The biggest difference between the two is when it comes to local functions. CL has
flet for defining local functions, and
labels for defining local functions that need to be able to call each other (or call themselves recursively). Here’s an example of each
;; A single local function (flet ((f (n) (+ n 10))) (f 5)) ;; Two local functions that don't need to call each other (flet ((f (n) (+ n 10)) (g (n) (- n 3))) (g (f 5)))
Here’s the equivalent code in Clojure. Note how the square brackets make things stand out a little bit more.
(letfn [(f [n] (+ n 10))] (f 5)) (letfn [(f [n] (+ n 10)) (g [n] (- n 3))] (g (f 5)))
If the functions need to reference each other, in CL you have to use
labels, instead of
flet. Here’s how that looks (the only difference is the form used; the arguments remain the same)
(labels ((a (n) (+ n 5)) (b (n) (+ (a n) 6))) (b 10))
In Clojure, you don’t need to use anything other than
letfn, because it already supports the recursive nature that
(letfn [(a [n] (+ n 5)) (b [n] (+ (a n) 6))] (b 10))
Finally, if you have local functions and other local bindings you need to establish, you can use a
let, but no recursion is supported. This is sort of like CL’s
flet but you can also use it for binding locals that are not functions
(let [a (fn [n] (+ n 5)) b (fn [n] (+ (a n) 6)) c 10] (b c))
I think the way Clojure uses square brackets in certain places that CL uses parentheses makes the code easier to read, overall.