Clojure Cheat Sheet
Clojure syntax, immutable data structures, persistent collections, and functional idioms for modern concurrent JVM programming.
2 PagesAdvancedMar 28, 2026
Basic Syntax
Bindings, control flow, and printing.
clojure
(def age 30)(def name "Ada")(def pi 3.14159)(if (>= age 18) (println name "is an adult") (println name "is a minor"))(doseq [i (range 5)] (println "Count:" i))
Collections
Persistent vectors, maps, and sequence functions.
clojure
(def nums [5 3 1 4 2]) ; vector (immutable)(def evens (filter even? nums)) ; (4 2)(def squared (map #(* % %) nums)) ; (25 9 1 16 4)(def total (reduce + nums)) ; 15(def sorted (sort nums)) ; (1 2 3 4 5)(def person {:name "Ada" :age 30}) ; map literal(:name person) ; "Ada", keyword-as-function lookup(assoc person :age 31) ; returns new map, original unchanged
Concurrency Primitives
Managed references for shared state.
clojure
(def counter (atom 0)) ; mutable reference, synchronous updates(swap! counter inc) ; atomically increments@counter ; deref, reads current value => 1(def account (ref 100)) ; coordinated (STM) reference(dosync (alter account - 30)) ; transactional update(future (Thread/sleep 1000) (println "done")) ; runs on another thread
Core Forms
Common Clojure special forms and macros.
- def- binds a symbol to a value in the current namespace
- defn- defines a named function
- let- creates local bindings scoped to a body of code
- fn / #()- anonymous function literal (long and shorthand forms)
- atom- uncoordinated, synchronous mutable reference type
- ->/->>- threading macros that thread a value through function calls
- keyword (:key)- self-evaluating symbol commonly used as a map key or accessor
Threading Macros
Flatten nested calls with thread-first and thread-last.
clojure
;; thread-first: inserts value as 1st arg(-> {:a 1} (assoc :b 2) (update :a inc) keys) ;=> (:a :b);; thread-last: inserts as last arg (great for seqs)(->> (range 10) (filter even?) (map #(* % %)) (reduce +)) ;=> 120;; as-> for mixed positions(as-> 5 x (+ x 3) (vector x x)) ;=> [8 8]
Destructuring
Bind nested map and sequence values in one form.
clojure
;; sequential(let [[a b & rest] [1 2 3 4]] [a b rest]) ;=> [1 2 (3 4)];; associative with defaults and :keys(defn greet [{:keys [name greeting] :or {greeting "Hi"}}] (str greeting ", " name))(greet {:name "Ada"}) ;=> "Hi, Ada";; keep the whole map with :as(let [{:keys [x] :as pt} {:x 1 :y 2}] [x pt])
Writing Macros
Compile-time code generation with defmacro.
clojure
(defmacro unless [test & body] `(if (not ~test) (do ~@body)))(unless false (println "runs!"));; ~ unquotes, ~@ splices a seq, ` is syntax-quote;; Inspect expansion:(macroexpand '(unless false (println "x")));=> (if (clojure.core/not false) (do (println "x")))
Sequence Functions
Core operations for transforming lazy sequences.
- map / mapv- apply a fn to each element (mapv returns a vector eagerly)
- reduce- fold a seq into a single value with an accumulator
- filter / remove- keep or drop elements matching a predicate
- partition / partition-by- split a seq into groups by size or by fn result
- group-by- build a map keyed by (f element)
- take-while / drop-while- slice a seq based on a predicate boundary
- into- pour one collection into another, optionally via a transducer
Pro Tip
Use the `->` and `->>` threading macros to flatten deeply nested function calls into a readable top-to-bottom pipeline, instead of reading inside-out.
Was this cheat sheet helpful?
Explore Topics
#Clojure#ClojureCheatSheet#Programming#Advanced#BasicSyntax#Collections#ConcurrencyPrimitives#CoreForms#DataStructures#Concurrency#CheatSheet#SkillVeris