Clojure and Interactive Programming

Clojure is a Lisp, the only language that is also beautiful. Hosted on the JVM for reach. Functional, expressive, opinionated.

I have been writing Clojure for five years, now professionally at United Signals on Flowniq: ClojureScript in the browser, Clojure and Datomic on the server, Malli schemas shared between the two. This page is the hub for what I think and write about Clojure, Lisp and interactive programming.

Start here

Interactive programming

The magic piece of Lisp is building the program while it runs. You do not write a file, compile it, run it and read the crash. You send one form to the running program, look at the answer, and change the next form. Small experiments become cheap enough to mesh with your thinking. It is a conversation with the program.

Posts on the craft:

Things I built with Clojure

Data orientedness

Clojure's style is what Yehonathan Sharvit calls data-oriented programming: separate code from data, represent data with generic data structures, keep data immutable.1 Not to be confused with data-oriented design in game development, which is about memory layout.

Data orientedness uses general data constructs and functions, something like JSON data and pure functions, to represent an information processing domain.

To model a library, we do not model books and librarians. We model the inventory book a librarian would use. We do not model students and courses, we model the student-course register.

Good data orientedness takes the traditions of accounting and bookkeeping seriously. A recorded fact is a fact. It is not updated afterwards; only a new fact, a correction, can be recorded. (This is exactly how Datomic works, and why it feels so natural to use from Clojure.)

Modeling students and courses as objects is good for a simulation, where the program should represent student behaviour. That is perhaps good in a game, but not in a library information system. Simula was made for simulation, and Simula 67 is generally regarded as the first object-oriented language.2 Object orientation was born to simulate things. Information systems are not simulations.

Clojure is weird

  1. It is a Lisp, which is a cleaning up of computer science. Alan Kay called the half-page Lisp evaluator in the LISP 1.5 manual "the Maxwell's equations of software".3 Lisp exists because it is closer to the truth of what programming is about. To improve on Lisp's paradigm, you would have to make actual discoveries in the fundamentals of programming. And doing so would not tell us that there is something better than Lisp, but more about the true nature of Lisp.
  2. It has pragmatism as part of its design philosophy.
  3. It has a tradition of craftsmanship that includes doing design. Not doing design work is bad Clojure programming.

Clojure 2 is an incoherent concept

A "Python 4" or a "Go 2" is a coherent idea: you take feedback, you design and implement, you make it better, you call it version n+1 and ship it.

For Clojure, this would be weird, because pragmatism is a core value of the language.

  1. Clojure is built to last. Change happens by growing: provide more, require less, and if something really must break, give it a new name.4
  2. Making a new language would take time and resources, which are weighed against the tradeoffs.
  3. Pragmatism means that doing nothing is on the table, like the null hypothesis in science. You have to ask: is doing the thing better than not doing anything?

So no law of nature prevents Clojure 2 from existing, but there is the next best thing: a (rational) memetic decision structure.

Given the right kind of knowledge d, namely Clojure's design philosophy, a rational person will not engage in behaviour X in the range of foreseeable situations E (a set of situations, an environment).

A possible situation outside of E is that the person simply has fun making Clojure 2. But pragmatic Clojure programmers have plenty of fun using Clojure creatively to solve other problems.

The pragmatic design philosophy, a meme, brings the behaviour of Clojure programmers closer to reality through design work, a form of error correction. Resources and tradeoffs are real. If error correction brings us closer to reality, we converge on the same reality. Otherwise it is bad error correction, or bad design work.

Great minds think alike, because they error correct. And good Clojure programmers behave alike. Clojure's pragmatism is analogous to rationality: both are cultures of error correction, cultures of conjecture and criticism [Popper, Deutsch].

Using Clojure for the sake of using Clojure would be bad Clojure programming

Sometimes the tradeoffs favour another language for getting a job done. A Clojure programmer is the first to say so.

Coercive programming constructs

Static types

Does a novelist say "all sentences must be between 5 and 15 words long"?

The program is the story; the source code is the text. Rules about the shape of the text do not make the story better.

Puzzle-oriented programming has its place, perhaps in education. It should play a minor role in solving real-world problems. Clojure's answer is to describe data where it matters, at the boundaries, with schemas (spec, Malli) that are themselves data.

Concretions

  • Wrapping information in bespoke classes, a Person, a Product, where plain data would do. Rich Hickey calls these data concretions, not data abstractions.5
  • Using the powerful tool of mini languages to express business logic, where a map would have done.

Open questions:

  • Where is the line between a good mini language and a concretion? Datalog is a mini language, and a good one.
  • Do LLMs, which read and write plain data effortlessly, make data orientedness more valuable or less?

Footnotes:

1

Yehonathan Sharvit, Data-Oriented Programming (Manning, 2022). Sharvit presents the principles as language-agnostic; Clojure embodies them.

2

Dahl and Nygaard. Simula I (1962–65) was the simulation language; Simula 67 added classes, objects, inheritance and virtual procedures.

3

A Conversation with Alan Kay, ACM Queue, 2004. He means the evaluator on page 13 of the LISP 1.5 Programmer's Manual.

4

Rich Hickey, Spec-ulation, Clojure/conj 2016: grow software by accretion and relaxation, never by breakage.

5

Rich Hickey, Effective Programs, Clojure/conj 2017 (transcript).


Generated by Claude on Benjamin Schwerdtner's behalf.

Date: 2025-10-03 Fri 19:53

Email: Benjamin.Schwerdtner@gmail.com

About
Contact