Clojure Impressions Round Two
Introduction
Let’s continue our Clojure related blog series (first article here).
Writing Clojure with IntelliJ IDEA and Cursive
I already told in my first Clojure article that I’m using IntelliJ IDEA with Cursive plugin. I resisted for years to switch from Eclipse to IntelliJ IDEA since I was working a lot as an onsite architect and most offsite developers were using Eclipse — it was a natural choice to use the same IDE and provide various examples and templates with that common IDE. But then I switched from Emacs to PyCharm for Python coding, then from Eclipse to IntelliJ IDEA for Java coding. And now IDEA+Cursive in Clojure coding. IDEA and Cursive provides excellent and highly productive IDE for writing Clojure. Let me give some examples.
Indentation works nicely. There is no need to be afraid of the Lisp parentheses since Cursive indents the code very nicely. And because Clojure is homoiconic IDE can really understand the code and do all kinds of magic with it. E.g. I use Emacs mode with Cursive. I have configured familiar Emacs Ctrl-K (in Emacs: kill-line: delete the rest of the current line and put it to the yank buffer) to mean “kill everything from the cursor location of the current S-expression to the end of that S-expression”. Java programmers just can’t realize how powerful this kind of editing can be. Because Clojure code is Clojure data structures ( = homoiconicity!) working with the IDE is really nice and productive. You almost certainly want to use Cursive editor in so called paredit mode for this reason. With paredit the IDE understands the S-expressions and you can slurp and barf the S-expressions in/out of other S-expressions with a single hot key. I believe if you have never tried some Lisp language with a great editor you just can’t understand what it is to write Lisp with a great editor — the productivity of writing code warps to the next level compared writing some imperative language like C or Java what ever great editor you have for it.
Using Clojure REPL
Clojure REPL — those Java guys just don’t understand what they miss (and believe me, I have been programming with Java some 18 years, I know). I have used Python REPL a lot, but Clojure REPL, and especially using Cursive REPL is just a tremendous joy, a great way to learn new Clojure concepts and also develop and test your code. I’m using the REPL all the time, and I guess that is very Lispic among all Lisp programmers — you do most of the stuff in the REPL. I use more than one monitor. I usually have my IDE editor windows open in one monitor and the REPL open in another monitor — this way you can see in one view a lot of conceptual stuff regarding your program. I use the excellent clojure.tools.namespace.repl to refresh recent code changes to my REPL: (do (require ‘[clojure.tools.namespace.repl :refer [refresh]]) (refresh)) , and then e.g. run the test again: (xyz.calculator-test/calculate-avgs-of-tiers-test) . If there is something odd in the test you just can’t figure out what it is, no problem. The calculator uses a list of maps which have some information regarding tiers to be calculated. Get the list in REPL and save it to some variable: (def my-tiers-list (xyz.db/get-tiers [6 21] [6 23])). Print the tiers in REPL: my-tiers-list => ({:tier 6, :level 21, :humidity 87, :temperature 23} {:tier 6, :level 22… Ok, data structure looks good, now feed it to the calculator in REPL: (xyz.calculator/calculate-avgs-of-tiers my-tiers-list) => {:tier 6, :humidity-avg 155.05…} … and you may find out there is something wrong with the humidity avg calculation.
How about editing code in REPL? Just like in the editor. It’s so beautiful. You can edit the code snippets in REPL just like you would in the editor — all indenting, slurping and barfing works just like in the editor. And with good hot keys between REPL window, REPL output window and editor window you can navigate between windows never leaving your fingertips from the keyboard. (Hint: A real Linux user assigns in the Linux keymap file the “i,j,k,l” buttons to work as arrow buttons with the Caps lock button (which you never need as a programmer — give it something better to do), this way with specific hot keys you can easily e.g. slurp/barf without ever needing to leave your fingertips from the classical qwerty position — if you use real 10 finger typing, which you should learn if you haven’t done that already.)
Writing Clojure Functions
Java and other imperative guys might wonder how you structure your code without objects. But the real question is: Do you really need objects? Objects with mutable state just tend to make things messy. Clojure basic data structures (lists, vectors and maps) work excellently with Clojure standard library functions. In backend programming you usually fetch some data out of the database, then process it somehow, and finally save the results to some other storage (whether it’s the same or another database, AWS S3, some queue etc.), or return the data as a http result. Clojure data structures and standard library just excells with this kind of backend processing. You fetch the data from the database and get a list of maps with database fields as keywords of the maps. Then filter the list, and feed the filtered list to map or reduce with your custom processing function — and you have the results. Let’s demonstrate. First create a simple list of maps in REPL: (def mylist ‘({:humidity 80} {:humidity 90})) . And then use reduce to calculate the average humidity: (/ (reduce (fn [sum item] (+ sum (:humidity item))) 0 mylist) (count mylist)) => 85. So, the reduce function is a higher-level function taking another function as parameter which it uses to calculate what ever you want to calculate. So, most processing looks as simple as (reduce (some-reduce-function) initial-value (filter (some-filtering-function your-data))) .
Conclusion
Be brave and give Clojure a try! It just might happen that you experience a huge warp in your productivity and you find the joy of programming in a completely new level! Do it today, go to https://clojure.org/ , download latest Clojure and start Lisp hacking. You may realize after a few weeks that there is no coming back to the old imperative world. A new Lisper has born!