Clojure
Purpose
Clojure pairs Lisp’s expressiveness with a serious platform: production JVM libraries, robust concurrency, and data-centric programming.
The Problem It Solves
Mutating shared state is where concurrent programs break. Clojure makes data immutable by default (persistent vectors/maps), manages identity change through atoms, refs, and agents, and lets macros build domain-specific syntax on top. Development is REPL-driven, so you can change running systems — the “live programming” workflow Lisp always promised.
Where It Fits
Clojure is the family’s modern general-purpose member: Lisp is the ancestor, AutoLISP is embedded in CAD, and Clojure targets backend services and data systems on the JVM — plus, via ClojureScript, the browser.
History
Clojure is the youngest Lisp and one of the few designed from scratch for a hosted platform.
Origins (2007)
Rich Hickey designed Clojure starting in 2007 and released it publicly in 2008; version 1.0 arrived in May 2009. The design goal was Lisp power plus a serious concurrency story on the JVM.
Milestones
- 2011 — ClojureScript compiles Clojure to JavaScript and wins the front end.
- 2012 — Datomic launches: Hickey’s immutable, time-aware database with a Datalog query engine.
- 2016–2020s — spec formalizes data validation; Cognitect stewards the language, then Nubank; 1.11/1.12 releases keep the core stable and additive.
Current Status
Mature and stable. An active core team and community maintain it; production users include Nubank, Walmart, and numerous banks and data teams; ClojureScript keeps one language across server and browser.
Stage
Clojure is production-grade with a deliberately conservative release culture.
Maturity
Fully mature: the API has been stable for years, releases are additive and rare, and giant deployments run in banks and data platforms.
Governance & Maintenance
A core team led by Rich Hickey and maintainers, public design discussions, and the Clojurists Together program fund ecosystem work. Licensed under the Eclipse Public License 1.0.
Popularity & Usability
A passionate, senior-learning community and consistent “most loved” survey rankings.
Adoption
Known users include Nubank (its core stack), Walmart, and various banks and fintechs; the ecosystem spans ClojureScript, data tooling, and machine-learning libraries (scicloj).
Learning Curve
Three things at once: Lisp syntax, immutable/functional thinking, and the JVM stack. The REPL and data-first culture reward steady practice; tools like Calva and Cursive remove most friction.
Tooling
Clojure CLI (deps.edn), Leiningen, VS Code with Calva, IntelliJ with Cursive, CIDER for Emacs, plus a mature REPL workflow (REPL-driven development is the community’s default practice).
Use Cases
Clojure shines for data-centric, stateful-without-mutation systems.
Primary Domains
- Backend services, APIs, and serverless functions.
- Data pipelines and ETL with immutable transformations.
- Domain modeling and business rules as data + functions.
- ClojureScript frontends, and scripting/gluing heavy JVM libraries.
Strengths
Immutability and persistent structures, sound concurrency primitives (atoms/refs/agents), seamless Java interop, macros for domain languages, and REPL-first development.
Weak Spots
A smaller hiring pool, slower cold start than plain Java, thinner library coverage in exotic domains, and non-JVM ports that always lag the mainline.
Performance
Clojure’s performance is the JVM’s performance — if you play by its rules.
Execution Model
The JIT compiles hot paths to native code. Persistent data structures give O(log32 n) updates; transients and transducers eliminate intermediate allocations; type hints and primitive arrays get numerics to Java speed.
Published Claims
Community and conference measurements show Clojure reaching Java-class throughput for compute-bound code when hints and arrays are used, while un-hinted boxed arithmetic is measurably slower. Every performance talk repeats the same rules: hint types, prefer transients, profile with Criterium, and don’t make persistence pay for what you don’t keep.
Example
A tiny Clojure program mixing a function, JVM interop, and a threading pipeline over data.
hello.clj
;; hello.clj — functions, interop, and threading data through steps
(defn shout [msg] ; defn defines a named function
(.toUpperCase msg)) ; JVM interop: java.lang.String method
(defn sum-even [n] ; thread-last macro pipes the data downward
(->> (range 1 (inc n)) ; 1..n as a lazy seq
(filter even? ) ; keep only even numbers
(reduce +))) ; sum them
(println (shout "hello clojure")) ; HELLO CLOJURE
(println (sum-even 100)) ; 2550
How to Run
# Install the Clojure CLI (clojure.org/guides/getting_started), then:
clojure # start a REPL
user=> (load-file "hello.clj") # run the script inside the REPL
# or with Babashka (fast scripting):
bb hello.clj
->> (thread-last) feeds each result into the last argument of the next call — the idiomatic way to read a data pipeline top-to-bottom. Immutable data means every step returns a new value; nothing is mutated in place.
Learn More
Official sources and free materials; the full categorized catalog is on the References & Downloads page.
Official Docs & Downloads
- clojure.org — rationale, guides, downloads, and the reference
- ClojureDocs — docs with community examples and gotchas
- Getting Started — install the CLI and start a REPL