« Back to article list

Clojure is Cool

Table of Contents

Clojure is Cool

So, maybe you have, or maybe you haven't heard of Clojure.

I had heard of it years ago, but never really gave it a lot of thought (or time) to it, despite being a huge fan of Common Lisp and a bit of a language polyglot. I think part of my initial reluctance may have been 'java' - as I would typically associate just the negatives to it (cumbersome language syntax, slow start up time, memory hog etc.).

About a month ago, I began listening to more of the Clojure talks by Rich Hickey (inventor of Clojure) as well as poking around the language a bit (checking out their new specification system, known as spec). It looked really neat! Despite being a bit of a 'static type' adherent, I could see a lot of merit in it. Anyways - this post is not about that - I had a need for some real work to be done, a customized browser for my own use, as recently GNU Icecat (Firefox 45 ESR), the browser I have used for many years, became mostly unusable. My lock-in to that older version was due to the Firefox 55+ quantum updates breaking my top level key binds, and introducing a massively gimped 'vim' like setup for my Firefox driving (I used Pentadactyl, and around the same time, a similar browser known as vimprobable2).

I needed a language I could easily get a GUI going on (preferably a light weight/simple one, such as webkit2). Doing a bit of shopping, I came across JavaFX (circa 2012) which integrates with webkit2 on all available OSes. Given that I love lisp and all, and Clojure was a lisp running on Java, it seemed like a perfect alignment of time and necessity that made me dive in and begin working on my own browser implementation, AHUBU (https://github.com/ahungry/ahubu).

So, enough with the backstory/ranting and on to why I believe it (Clojure) is cool.

REPL driven development

This is the single biggest selling point to most lisps (and the overbearing factor in my love for them), and is completely unique, not just to development compared to a 'typical' language (compiled or interpreted), but unique/superior even to other languages that lean towards a REPL based approach (J / APL / Prolog / Elixir) of programming and trying out some code.

I like to term this as 'time between cause and effect' - or the time it takes between making a change, and seeing the result of that change.

In a compiled language, this is usually very large - a programmer will update the program, recompile it, execute it, and finally see the result of the change.

In an interpreted language, this is slightly less - the compilation step is removed.

In a test driven development (TDD) methodology, this is even less - the execute it scope is reduced from the entire world of the software, to the specific segment of code being developed (but, this requires a lot of boilerplate, and even the test runner is not always tightly coupled to an individual test at the editor level).

Some of the languages that offer a pleasant REPL experience (even PHP and Nodejs give a decent built in REPL) still run into the problem of having 2 separate environments - there is the actual world of the software (the execution runtime), and then an isolated 'interactive' environment - often a very manual and ephemeral experience - the user runs code - those commands run simply disappear when the session ends etc.

What if there was a coupling between the code itself, at an individual snippet level, and the REPL environment? And what if the REPL environment and the execution runtime/world were one in the same? With lisp(s), that's the case!

It was a bit mind blowing my first time trying it - "do I type code in the REPL and it saves it to a source file somewhere?" I asked myself (or perhaps some kind folks in IRC)? No! You actually modify your program in your source file, select an s-expression (a block of code surrounded by parenthesis) and evaluate just that block of code in your running REPL / runtime image. It was a bit mind blowing to realize, and a great revelation was revealed, as it became clear that all those parenthesis were for a very good reason (for this interactive functionality to work well - imagine trying to re-evaluate a single snippet of code in ANY other non-lisp language - good luck writing a parser that can handle redefining a single method without having to 'hot reload' an entire file (or, in many cases, an entire project!). Lets just say, it makes all those other times between cause and effect appear to be eons (even those of you who may have tried out front end with 'fast' hot module reloading like typescript fusebox, or create-react-app - try out something like Clojurescript and fighweel - you will not want to go back).

Clear, readable, and concise code

As I mentioned earlier - lately I've been a bit of a type adherent - things should all be strictly and statically typed! How can anyone read the code and know it should do what it's supposed to do without the types! Well - a lot of the time its just extra noise and hoops to jump through. Rich Hickey made a great reference about using 'tests' (unit tests, TDD) as a guard rail during driving, and has alluded to similar for heavily typed systems. When we drive, do we just let the car run against the guard rail to guide us to where we're going? or do we make an intelligent decision to follow the road on our own? Clojure (and lisps like Common Lisp / Emacs Lisp) are the latter, and the code to REPL to feedback cycle is the car on the road.

To illustrate the conciseness and the beauty of the code, lets compare two practical examples of achieving a task in Clojure vs Java - in this case, the task of extending JavaFX to use persistent cookies (cookies that are saved after closing and re-opening a browser).

Extending JavaFX cookie handler to use persistent storage

I will go over it, broken down by class/need, and then by language.

Also - thanks to Manish for the github gist - it was a useful reference:

https://gist.github.com/manishk3008/2a2373c6c155a5df6326

Serializing the output / writing to disk (persistent storage)

Shadowing or reimplementing a built in cookie store (tracking writes to disk)

Conclusion

In conclusion, I hope you give Clojure (or most any lisp) a try - they are really great languages and worth using!

Let me know! m @ ahungry dot com (put it together :p )

Or hit me up on on Twitter @ahungry