Clojure is defined in terms of the evaluation of data structures, not of a character syntax. The reader reads the next form from a stream of characters and returns the data it stands for; the compiler then sees only that data. The reader (the function read) is also useful alone, much as one would use JSON or XML. The rules below follow the Clojure reference page on the reader and the source of the reader, LispReader.java.
White space, delimiters and tokens
White space separates forms. It is the white-space characters of Java (Character.isWhitespace) and the comma, so {:a 1, :b 2} and [1,2,3] need no other separator.
A token (a symbol, keyword, number, nil, true or false) runs until white space or a terminating macro character. The terminating macro characters are these thirteen:
" ; @ ^ ` ~ ( ) [ ] { } and \
The macro characters #, ' and % do not terminate a token, so a'b, a#b and x% are single symbols (which is why x#, the auto-gensym of a syntax-quote, is one symbol). a@b is the symbol a followed by a deref of b.
Macro characters
Reading is driven by a table that maps a character to a reader macro. The built-in table has these entries; user programs cannot change it, though *data-readers* adds tagged literals.
| Character | Reads |
|---|---|
" | a string |
; | a comment to the end of the line |
' | 'form is (quote form) |
@ | @form is (deref form) |
^ | metadata: reads the metadata form, then the form it goes on |
` | syntax-quote (see Macros) |
~, ~@ | unquote and unquote-splicing, inside a syntax-quote: (clojure.core/unquote x) and (clojure.core/unquote-splicing x) |
( | a list |
[ | a vector |
{ | a map (an odd number of forms is an error) |
) ] } | an error when there is no open form to close: unmatched delimiter |
\ | a character |
% | an argument of a #( ) function literal: %, %1 to %n and %&; elsewhere an ordinary symbol |
# | the dispatch macro: the next character picks the reader (the table below) |
Symbols
- A symbol begins with a non-numeric character and can contain letters, digits and
*+!-_'?<>=(the reference says that other characters may be allowed eventually). The reader itself takes any character that is not white space or a terminating macro character into a token, so$,%,#and non-ASCII letters appear in real symbols. /separates a namespace from a name, once, in the middle:my-namespace/foo./alone names the division function. A symbol that contains/or.is called qualified..in the middle of a symbol makes a fully qualified class name or a namespace name (java.util.BitSet). Symbols beginning or ending with.are reserved:(Foo. …)is a constructor call and.methoda method call.- Symbols beginning or ending with
:are reserved. A symbol can contain one or more non-repeating:. &is reserved for syntax (rest parameters) and cannot be a local name.Outer$Innernames an inner class.String/2andlong/1(Clojure 1.12) name array classes: a class, a/and a dimension from 1 to 9.- The names
nil,trueandfalseare read as the values, not as symbols.
Keywords
A keyword is like a symbol but begins with :, evaluates to itself, and is compared by identity. It can have a namespace, :person/name, which may contain dots. A keyword that begins with two colons is auto-resolved when it is read:
| Written | Read as |
|---|---|
:rect | the keyword rect, no namespace |
:shape/rect | the keyword rect in namespace shape |
::rect | the current namespace: in user, :user/rect |
::x/foo | the namespace is resolved through the aliases of the current namespace: with x aliased to example, :example/foo |
Numbers
A token that starts with a digit, or with + or - followed by a digit, must be a valid number. The reader matches it against three patterns:
| Form | Syntax | Examples | Read as |
|---|---|---|---|
| Decimal integer | optional sign, 0 or a digit 1–9 then digits | 0 42 -7 +5 | Long when it fits, else BigInt |
| Hexadecimal | 0x or 0X, hex digits | 0x2A 0XFF | as above |
| Octal | 0 then octal digits | 052 | as above (08 is an error) |
| Radix | radix 1–99 (valid 2–36), r or R, digits and letters | 2r101010 36rZ 8r52 | as above; 2r102 is an error |
| BigInt | any integer form followed by N | 10N 0xFFN | clojure.lang.BigInt |
| Ratio | integer / integer (no sign on the denominator) | 22/7 -1/2 | clojure.lang.Ratio (reduced; 4/2 reads as 2) |
| Floating point | digits, optional . and digits, optional exponent e or E with a signed integer | 1.5 1. 2e3 1.5e-3 | Double |
| BigDecimal | a floating-point form followed by M | 1.5M 10M 1e3M | java.math.BigDecimal |
| Symbolic values | ##Inf ##-Inf ##NaN | the Double constants (Clojure 1.9) |
A digit string with a leading zero that is not octal, such as 08, is an invalid number, but 08.5 is the double 8.5. A token such as 1a is an error. .5 is not a number (it is a symbol); write 0.5. The viewer colours a token as a number only if it matches these patterns.
Strings
A string is enclosed in double quotes and may span lines. The escape sequences are:
| Escape | Character |
|---|---|
\t \r \n | tab, carriage return, line feed |
\b \f | backspace, form feed |
\\ \" | a backslash, a double quote |
\uNNNN | the UTF-16 unit with four hexadecimal digits |
\NNN | an octal escape of up to three digits, 0 to 377 |
Any other escape is an error. There is no triple-quoted text block: a documentation string is an ordinary string, and a multi-line string simply contains line feeds. A string that is the second form of def, defn, ns, defprotocol and similar forms is documentation (see Namespaces and vars).
Characters
A backslash and a character make a character literal. The reader takes the first character after the backslash, whatever it is, and then reads on to the end of the token, so \( is a character and \a) ends at the parenthesis.
| Literal | Character |
|---|---|
\a \é \( | that character |
\newline \space \tab \formfeed \backspace \return | the named white space characters |
\uNNNN | the UTF-16 unit with four hex digits (a surrogate half is an error), for example \u03A9 for the Greek capital omega |
\oNNN | an octal code of up to three digits, at most \o377 |
Regular expressions
#"pattern" is read and compiled at read time to a java.util.regex.Pattern. Backslashes in the pattern are kept as they are and need no doubling: #"\s*\d+" is the same as (re-pattern "\\s*\\d+"). A \ still protects the next character, so #"a\"b" holds a quote. (In ClojureScript the same literal is a JavaScript RegExp.)
Comments and discarded forms
| Form | Meaning |
|---|---|
; … | to the end of the line (a line feed or a carriage return) |
#! … | also a line comment, so a script may start with a shebang line |
#_ form | the reader reads the next form and throws it away completely. It nests: #_ #_ a b discards both a and b. Anything is allowed inside the discarded form that the reader can read, so a discarded form must still be well formed (balanced, with valid tokens) |
(comment …) | an ordinary macro, not syntax: it returns nil and the forms inside are read like any code, so they must be readable, but they are not evaluated |
(+ 1 #_(this is skipped) 2) ; => 3
[1 #_2 3] ; => [1 3]
#_ #_ ignored also-ignored (f) ; the next form is (f)
(comment (f 1) (g 2)) ; => nil
Metadata
^ reads the metadata first and then the form it applies to. Metadata is a map attached to symbols, lists, vectors, sets, maps, tagged literals that return an object that takes metadata, and record, type and constructor calls. Several forms exist:
| Written | Means |
|---|---|
^{:a 1 :b 2} [1 2 3] | the vector with that map as its metadata |
^String x | ^{:tag java.lang.String} x: a symbol or string is a :tag, a type hint |
^:dynamic x | ^{:dynamic true} x: a keyword is a flag set to true |
^[String long _] | ^{:param-tags [String long _]}: a vector gives parameter tags for a qualified method (1.12) |
^:a ^:b x | chained: the maps are merged from right to left |
#^String x | the older spelling of ^, still read |
The # dispatch forms
The dispatch macro reads the next character and uses a reader from a second table.
| Written | Reads |
|---|---|
#{ … } | a set |
#( … ) | a function literal: #(+ % 1) is (fn [p1] (+ p1 1)). % is %1, %n is the nth argument, %& collects the rest. #( ) cannot be nested |
#"…" | a regular expression |
#'x | (var x) |
#_ | discard the next form |
#?( … ), #?@( … ) | a reader conditional and a splicing reader conditional (ClojureScript and .cljc) |
#:ns{ … }, #::{ … }, #::alias{ … } | a map in which keys without a namespace get a default one (see Data structures) |
##Inf ##-Inf ##NaN | symbolic values |
#=( … ) | evaluate at read time (only when *read-eval* allows it, and never for untrusted input) |
#! | a line comment |
#^ | metadata, the old syntax |
#< | unreadable: always an error (printed objects such as #<Foo> cannot be read back) |
#tag form | a tagged literal, when the character after # is a letter |
#my.Type[ … ], #my.Record{ … } | a constructor call of a Java class, a deftype or a defrecord, given as the fully qualified name before a vector (positional arguments) or a map (record fields). The arguments are not evaluated |
Tagged literals
#tag form reads form as data and passes it to the reader function for tag. Tags without a namespace are reserved for Clojure. The built-in ones are:
| Tag | Form | Result |
|---|---|---|
#inst | a string "yyyy-mm-ddThh:mm:ss.fff+hh:mm", parts after the date optional | a java.util.Date by default; clojure.instant/read-instant-calendar and read-instant-timestamp give a Calendar or a Timestamp (Clojure 1.4) |
#uuid | a string such as "3b8a31ed-fd89-4f1b-a00f-42e3d60cf5ce" | a java.util.UUID (Clojure 1.4) |
Other tags are found in *data-readers*, which at start-up is filled from every data_readers.clj or data_readers.cljc file at the root of the classpath: each holds a map from a tag symbol to the var that reads it ({foo/bar my.project.foo/bar}). A tag with no reader goes to *default-data-reader-fn*; if that is nil (the default) the reader throws. tagged-literal is a function that stores such a literal as an object with :tag and :form. ClojureScript adds #js (a JavaScript object or array from a map or vector) and #queue.
Not described
Known, not yet covered
- Reference: the printer (
pr,*print-readably*,print-method,*print-namespace-maps*) is only mentioned;core_print.cljwas downloaded but not tabulated. - Reference: reader options (
:eof,:read-cond,:features,*read-eval*,*reader-resolver*) are named here and on the ClojureScript page but their effect on every form was not tested. - Viewer: a regular expression is coloured as one regex token; its own syntax (groups, classes) is not coloured, and escapes in strings are not coloured separately.
Unknown
- Reference: the table of which symbol characters work beyond the documented set comes from reading
LispReader.java(a symbol is matched by[:]?([\D&&[^/]].*/)?(/|[\D&&[^/]][^/]*)); it was not run against a JVM.
See also
- EDN – the subset of this syntax that is a data format
- Macros and syntax-quote – what the quote marks do
- Common Lisp: lexical structure and Racket: lexical structure – the readers of other Lisps