I can’t remember how I stumbled across Rich Hickey’s paper about the history of Clojure or why I decided to read it, apart from it being in a stage when I was feeling like the books I was reading were taking a long time and I wanted some quick wins. It is short, only around 40 pages, so it certainly fit the bill.

The “why” of Hickey starting Clojure: trivially, he was pursuing a project that interested him during a self-funded sabattical. Secondly, he had experienced effectiveness programming in Lisp, but had limited opportunities to apply the things he liked about it to his professional career.

Lisp influences

The Lisp ideas he wanted were: “code as data; independent read/print; small core; the REPL; and extreme flexibility”. I’m not experienced in any of the Lisp ideas except for the ways in which they exist in Ruby, which has a REPL and can approximate some of the code as data and flexibility ideas with metaprogramming and dynamic typing (and the inventor of Ruby does credit Lisp as a source of inspiration). The value for me here (more on this later) was about how to bring new ideas to a programming community.

He had attempted some of his Lisp ideas in a C# project with good results, but the code that resulted was not idiomatic and people new to the project did not appreciate the value. Instead of persisting with those ideas in C#, he decided to create a new language.

Information system language friendliness

In addition to the Lispy bits, Clojure added features friendly to programmers who build systems that model real-world information. The discussion of these is an interesting way of looking at some things that most professional programmers know intuitively:

If your program deals with information, these are among your primary problems: information is sparse, incrementally accumulated, open / extensible, conditionally available, formed into arbitrary sets in different contexts, merged with other information etc. Thus the answers to these questions become important: Can you determine what information is present? Is there an algebra for information selection? Merging? How difficult is it to accumulate information in a processing pipeline?…

This was eye-opening as I had never thought that a language could optimise for these things. Languages make some things difficult and some things less difficult and you do the best you can with limited influence over those tools, or so I thought. To think of a new language being built from scratch to do things that I care about is different.

That idea was also novel to people who really do design languages, apparently. Hickey relates his disappointment at a conversation he heard where two language designers were horrified that a colleague had to do some programming involving a database. This demonstrated their separation from and lack of interest in programming in the real world. He didn’t want his language to be similarly divorced from “reality”.

Lesson: making ideas useful for the things people care about

With significant parts of the paper being over my head (I’m not ashamed to admit, as someone with zero prior knowledge of Clojure and functional programming), the lesson that has stuck with me is: if you have ideas that you believe are worthwhile for other people, package them with things that are undeniably useful to them. This may involve going beyond the purest form of the original ideas.

Clojure is now my “reference implementation” of the concept. Clearly he wasn’t able to convince people of the ideas in the abstract, or he wouldn’t have needed to self-fund its development. Even though it was self-funded, Hickey chose to make Clojure good for commercial programming with his choice of data structures and easy compatability with the JVM ecosystem.

My personal interest in this concept is in thinking about how to drive the ideas that I think are worthwhile in my work and I’d like my colleagues to adopt. I have to understand the costs in changing to a new thing (even if they are only emotional) and be able to demonstrate (or at least articulate) the value gained in exchange. If the costs are significant, perhaps there is something I can deliver to make them less costly.

  • If I want programmers to be better at logging, maybe I need to build better logging tools
  • If I want code to be called in a certain way, maybe I need to deliver a library that makes it easy to do and seems trustworthy

… and so on.

Side note: Static vs Dynamic Typing

I tackle this last just because it’s interesting, but not the main lesson of the paper for me.

The paper takes more than a few potshots at static typing. Whether a piece of information is required or nullable and how it combines with other information is context dependent, and this makes for a poor match with classes whose shape must be decided forever before a program starts running. Hickey makes a good point: classes are abandoned in a lot of static code in favour of hashes and vectors that are handled more flexibly. Unfortunately these more ad hoc structures have less language support than classes do, so the programmer is left at a disadvantage. Clojure does not offer static typing, and instead offers that support.

Another idea is that the tooling that is often advanced in favour of static typing is considered a symptom of a problem:

Type errors, pattern matching errors and refactoring tools are venerated for facilitating change instead of being recognised as underscoring (and perhaps fostering) the coupling and brittleness in a system.

I’ve only spent significant time with one of each language family (Java and Ruby respectively) and I definitely prefer Ruby. Nothing about the type system in Java seems like it would catch the sort of errors that I experience now. That said, I have heard that the arguments against static typing are really talking about bad static typing, and Java is normally the chief culprit named. Perhaps a Haskell or Elm would have something useful to me.