Structuring the Code
Web Development with Clojure, Third Edition — by Dmitri Sotnikov, Scot Brown (74 / 107)
👈 Being Lazy | TOC | Destructuring Data 👉
One nontrivial difference between Clojure and imperative languages is the way the code is structured. In imperative style, it’s a common pattern to declare a shared mutable variable and modify it by passing it different functions. Each time we access the memory location, we see the result of the code that previously worked with it. For example, if we have a list of integers and we wish to square each one and then print the even ones, the following Python code would be perfectly valid:
l = list(range(1, 6))
for i, val in enumerate(l) :
l[i] = val * val
for i in l :
if i % 2 == 0 :
print(i)
In Clojure this interaction has to be made explicit. Instead of creating a shared memory location and then having different functions access it sequentially, we chain functions together and pipe the input through them:
(run! println
(filter #(= (mod % 2) 0)
(map #(* % %) (range 1 6))))
Or, as we’ve covered, we could use the ->> macro to flatten the operations:
(->> (range 1 6)
(map #(* % %))
(filter #(= (mod % 2) 0))
(run! println))
Each function returns a new value instead of modifying the existing data in place. You may think that this can get…