Clojure programs are data. Each literal form below is what the reader produces. All the data structures are immutable, can be read back from their printed form, have value equality and good hash values, and the collections are manipulated through interfaces, support sequencing, persistent modification and metadata, and implement the read-only part of java.util.Collection or java.util.Map.
Scalar values
| Kind | Literal | Notes |
|---|---|---|
| nil | nil | Java null; a possible value of any type; logical false; the end of a sequence |
| Boolean | true false | only nil and false are logically false: everything else, including 0 and "", is true |
| Long | 42 0x2A 2r101010 | the default integer, a Java long. An operation that overflows throws ArithmeticException; the operators +' -' *' inc' dec' promote to BigInt instead |
| BigInt | 10N | arbitrary size; an integer too large for a Long also reads as one |
| Ratio | 22/7 | division of integers that does not reduce to an integer yields a ratio rather than a float |
| Double | 3.14 1e10 | floating point; ##Inf ##-Inf ##NaN are the special values |
| BigDecimal | 3.14M | exact decimal |
| String | "text" | a Java String, immutable, may contain line feeds |
| Character | \a \newline \u03A9 | a Java Character |
| Symbol | my-fn clojure.string/join | a name; evaluates to what it is bound to; carries optional namespace and metadata |
| Keyword | :name :ns/name ::auto | a name that evaluates to itself and works as a function that looks itself up in a map: (:a {:a 1}) is 1 |
| Regular expression | #"\d+" | a java.util.regex.Pattern |
| Instant, UUID | #inst "2018-03-28" #uuid "…" | tagged literals: java.util.Date and java.util.UUID |
Numbers follow contagion: an integer operation that involves a BigInt gives a BigInt, and any operation that involves a double or float gives a double. (== 1 1.0 1M) is true, (/ 2 3) is 2/3, and (/ 2.0 3) is 0.6666666666666666. = is stricter than ==: it is false across integer and floating-point categories, so (= 1 1.0) is false.
Collections
| Collection | Literal | Interface | Behaviour |
|---|---|---|---|
| List | '(1 2 3) or (list 1 2 3) | IPersistentList, ISeq | count is O(1); conj adds at the front; peek and pop treat it as a stack. Unquoted, a list is a call to be evaluated |
| Vector | [1 2 3] | IPersistentVector | indexed by integers in log32 N steps; conj adds at the end; rseq reverses; a vector is a function of its index: ([10 20] 1) is 20 |
| Map | {:a 1, :b 2} | IPersistentMap | keys and values are any forms; hash maps need keys with hashCode and equals; sorted maps need Comparable keys or a comparator; a map is a function of its keys. Small maps may be array maps (array-map) that keep insertion order |
| Set | #{:a :b} | IPersistentSet | unique values; disj removes; contains? and get test; a set is a function of its members: (#{:a} :a) is :a, (#{:a} :k) is nil |
| Queue | none (clojure.lang.PersistentQueue/EMPTY) | IPersistentCollection | first in, first out; conj at the rear, peek and pop at the front. ClojureScript has the literal #queue [] |
| Record | #my.ns.Point{:x 1 :y 2} after defrecord | map interfaces | see Protocols, records and multimethods |
| StructMap | none (defstruct, struct) | map | the older way to fix a set of keys; records now serve better |
Every collection supports count, conj ("adding" in the way that is natural to it) and seq. Because of seq, every sequence function works on any collection. (seq []) is nil.
Map namespace syntax
Since Clojure 1.9 a map can give a default namespace to its keys: #:ns{ … }. Keys that are keywords or symbols without a namespace get it; keys with a namespace are unchanged, except the namespace _, which is removed (so a key can be left without a namespace). #::{ … } and #::alias{ … } resolve the namespace like ::kw does. Values are not changed.
#:person{:first "Han"
:last "Solo"
:ship #:ship{:name "Millennium Falcon"}}
;; is read as
{:person/first "Han"
:person/last "Solo"
:person/ship {:ship/name "Millennium Falcon"}}
Equality, hashing and metadata
- Collections of the same category are equal when their elements are equal:
(= [1 2] '(1 2))is true (sequential), while a map never equals a vector or a set. - Two hash values exist: the Java
hashCodethat every Clojure collection computes as the Java interfaces demand, and Clojure's own better-distributed hasheq, whichhashreturns and which theIHashEqinterface marks. - Metadata is a map that rides on a symbol or a collection without affecting equality:
(with-meta [1 2 3] {:a 1}),(meta x),(vary-meta x f); written with^in source. - Collections are efficient to "change" because new versions share structure with the old one (they are persistent) and safe to share between threads. A
transientgives a temporary, faster, mutable view of a vector, map or set that is made withpersistent!when done (see Evaluation).
Related functions
| For | Names |
|---|---|
| create | list list* vector vec vector-of hash-map sorted-map sorted-map-by array-map hash-set sorted-set sorted-set-by set zipmap |
| read | get get-in nth first peek rseq contains? find keys vals key val select-keys count subseq rsubseq |
| "change" | conj assoc assoc-in update update-in update-keys update-vals dissoc disj pop subvec merge merge-with into empty |
| test | list? vector? map? set? coll? seq? sequential? associative? counted? sorted? reversible? indexed? seqable? empty? record? map-entry? |
| relations and sets | clojure.set: union difference intersection select project rename rename-keys index join map-invert subset? superset? |
| nested data | clojure.walk, clojure.zip, clojure.data/diff (see the standard library) |
Not described
Known, not yet covered
- Reference: the complexity of every operation of every collection and the internals (HAMT and the 32-way trie) are not described;
clojure.data.avl,clojure.core.rrb-vector,data.priority-mapand other collection libraries are not covered. - Reference: numeric edge cases (unchecked and primitive maths,
*math-context*,*unchecked-math*, primitive arrays) are named only on Java interop.
Unknown
- Reference: that
4/2reads as the integer2and that(seq [])isnilis stated from the behaviour of the language and not from a page of the downloaded reference; no JVM was available to run it.
See also
- Sequences and laziness – functions that work on every collection
- EDN – these literals as a data format