In a post in the “Extreme OO in Practice” series (in Polish), KozioĊek used the following example: Fill a 3x3x3 matrix with subsequent natural numbers and print it to stdout.
The example in Java is 27 lines of code (if you remove comments). It is later refactored into 55 lines that are supposed to be more readable, but personally I can’t help but gnash my teeth over it.
Anyway, shortly after reading that example, I thought of what it would look like in Clojure. Here it is:
(def array (take 3 (partition 3 (partition 3 (iterate inc 1))))) (doall (map #(doall (map println %)) array))
That’s it. I know it’s unfair to compare this to Java and say that it’s shorter than your class and main()
declaration. But it is, and it makes the full-time Java programmer in me weep. Anyway, I have two observations.
As I like to point out, Java is awfully verbose and unexpressive. Part of the story is strong typing and the nature of imperative programming. But then again, sometimes imperative programming is very clumsy.
Secondly, this solution in Clojure presents a completely different approach to solving the problem. In Java you would declare an array and then iterate over it in nested loops, incrementing the “current value” in every innermost iteration. In Clojure, you start with an infinite sequence of lazy numbers, partition (group) it in blocks (that’s one row), then group those blocks into a 2D array, and take 3 of those 2D blocks as the final 3D matrix. Same thing with printing the array. You don’t iterate over individual cells, but naturally invoke a function on a sequence.
The difference is subtle, but very important. Note how the Java code needed 4 variables for the filling (“current value” and 3 indexes) and 3 indexes for printing. There was a very clear distinction between data and what was happening to it. In Clojure you don’t need to bother with such low-level details. Code is data. Higher-order functions naturally “serve as” data in the first line, and are used to iterate over this data in the second.