(1 "two" 3.0)
( … )
- List[ … ]
- Vector{ … }
- Map#
- Dispatch character#{ … }
- Set#_
- Discard#"…"
- Regular Expression#(…)
- Anonymous function#'
- Var quote##
- Symbolic values#inst
, #uuid
, and #js
etc. - tagged literals%
, %n
, %&
- Anonymous function arguments@
- Deref^
(and #^
) - Metadata'
- Quote;
- Comment:
- Keyword::
- Auto-resolved keyword#:
and #::
- Namespace Map Syntax/
- Namespace separator\
- Character literal$
- Inner class reference->
, ->>
, some->
, cond->
, as->
etc. - Threading macros`
- Syntax quote~
- Unquote~@
- Unquote splicing<symbol>#
- Gensym#?
- Reader conditional#?@
- Splicing Reader conditional*var-name*
- "Earmuffs">!!
, <!!
, >!
, and <!
- core.async channel macros<symbol>?
- Predicate Suffix<symbol>!
- Unsafe Operations_
- Unused argument,
- Whitespace character#=
Reader evalThis page explains the Clojure syntax for characters that are difficult to "google". Sections are not in any particular order, but related items are grouped for ease. Please refer to the reader reference page as the authoritative reference on the Clojure reader. This guide is based on James Hughes original blog post and has been updated and expanded here with the permission of the author.
( … )
- ListLists are sequential heterogeneous collections implemented as a linked list.
A list of three values:
(1 "two" 3.0)
[ … ]
- VectorVectors are sequential, indexed, heterogeneous collections. Indexing is 0-based.
An example of retrieving the value at index 1 in a vector of three values:
user=> (get ["a" 13.7 :foo] 1)
13.7
{ … }
- MapMaps are heterogeneous collections specified with alternating keys and values:
user=> (keys {:a 1 :b 2})
(:a :b)
#
- Dispatch characterYou’ll see this character beside another e.g. #(
or #"
.
#
is a special character that tells the Clojure reader (the component that takes Clojure
source and "reads" it as Clojure data) how to interpret the next character using a read table. Although some Lisps allow the read table to be extended by users, Clojure does not.
The #
is also used at the end of a symbol when creating generated symbols inside a syntax quote.
#{ … }
- SetSee #
for additional details.
#{…}
defines a set (a collection of unique values), specifically a hash-set
. The
following are equivalent:
user=> #{1 2 3 4}
#{1 2 3 4}
user=> (hash-set 1 2 3 4)
#{1 2 3 4}
Sets cannot contain duplicates and thus the set
reader will throw an exception in this case as it is an invalid literal. When items are added to a set, they are simply dropped if the value is already present.
user=> #{1 2 3 4 1}
Syntax error reading source at (REPL:83:13).
Duplicate key: 1
#_
- DiscardSee #
for additional details.
#_
tells the reader to ignore the next form completely.
user=> [1 2 3 #_ 4 5]
[1 2 3 5]
Note that the space following #_
is optional, so
user=> [1 2 3 #_4 5]
[1 2 3 5]
also works. Also note that the discard character works in edn.
A neat trick is that multiple #_
can be stacked to omit multiple forms
user=> {:a 1, #_#_ :b 2, :c 3}
{:a 1, :c 3}
The docs suggest that "The form following #_
is completely skipped by the reader
(This is a more complete removal than the comment
macro which yields nil
).".
This can prove useful for debugging situations or for multiline comments.
#"…"
- Regular ExpressionSee #
for additional details.
#"
indicates the start of a regular expression
user=> (re-matches #"^test$" "test")
"test"
This form is compiled at read time into a host-specific regex machinery, but it is not available in edn. Note that when using regexes in Clojure, Java string escaping is not required
#(…)
- Anonymous functionSee #
for additional details.
#(
begins the short hand syntax for an inline function definition. The
following two snippets of code are similar:
; anonymous function taking a single argument and printing it
(fn [line] (println line))
; anonymous function taking a single argument and printing it - shorthand
#(println %)
The reader expands an anonymous function into a function definition whose
arity (the number of arguments it takes) is defined by how the %
placeholders
are declared. See the %
character for discussion around arity.
user=> (macroexpand `#(println %))
(fn* [arg] (clojure.core/println arg)) ; argument names shortened for clarity
#'
- Var quote#'
is the var quote which expands into a call to the var
function:
user=> (read-string "#'foo")
(var foo)
user=> (def nine 9)
#'user/nine
user=> nine
9
user=> (var nine)
#'user/nine
user=> #'nine
#'user/nine
When used it will attempt to return the referenced var. This is useful when
you want to talk about the reference/declaration instead of the value it represents.
See the use of meta
in the metadata (^
) discussion.
Note that var quote is not available in edn.
##
- Symbolic valuesClojure can read and print the symbolic values ##Inf
,
##-Inf
, and ##NaN
. These are also available in edn.
user=> (/ 1.0 0.0)
##Inf
user=> (/ -1.0 0.0)
##-Inf
user=> (Math/sqrt -1.0)
##NaN
#inst
, #uuid
, and #js
etc. - tagged literalsTagged literals are defined in edn and supported by the Clojure and
ClojureScript readers natively. The #inst
and #uuid
tags are defined by edn,
whereas the #js tag is defined by ClojureScript.
We can use Clojure’s read-string
to read a tagged literal (or use it directly):
user=> (type #inst "2014-05-19T19:12:37.925-00:00")
java.util.Date ;; this is host dependent
(read-string "#inst \"2014-05-19T19:12:37.925-00:00\"")
#inst "2014-05-19T19:12:37.925-00:00"
A tagged literal tells the reader how to parse the literal value. Other common
uses include #uuid
for expressing UUIDs and in the ClojureScript world an
extremely common use of tagged literals is #js
which can be used to convert
ClojureScript data structures into JavaScript structures directly. Note that
#js
doesn’t convert recursively, so if you have a nested data-structure, use
js->clj
.
Note that while #inst
and #uuid
are available in edn, #js
is not.
%
, %n
, %&
- Anonymous function arguments%
is an argument in an anonymous function (…)
as in (* % %)
.
When an anonymous function is expanded, it becomes an fn
form and %
args are replaced with gensym’ed names
(here we use arg1, etc for readability):
user=> (macroexpand `#(println %))
(fn* [arg1] (clojure.core/println arg1))
Numbers can be placed directly after the %
to indicate the argument positions (1-based).
Anonymous function arity is determined based on the highest number %
argument.
user=> (macroexpand `#(println %1 %2))
(fn* [arg1 arg2] (clojure.core/println arg1 arg2)) ; takes 2 args
user=> (macroexpand `#(println %4))
(fn* [arg1 arg2 arg3 arg4] (clojure.core/println arg4)) ; takes 4 args doesn't use 3
You don’t have to use the arguments, but you do need to declare them in the order you’d expect an external caller to pass them in.
%
and %1
can be used interchangeably:
user=> (macroexpand `#(println % %1)) ; use both % and %1
(fn* [arg1] (clojure.core/println arg1 arg1)) ; still only takes 1 argument
There is also %&
which is the symbol used in a variadic anonymous function
to represent the "rest" of the arguments (after the highest named anonymous
argument).
user=> (macroexpand '#(println %&))
(fn* [& rest__11#] (println rest__11#))
Anonymous functions and %
are not part of edn.
@
- Deref@
expands into a call to the deref
function, so these two forms
are the same:
user=> (def x (atom 1))
#'user/x
user=> @x
1
user=> (deref x)
1
user=>
@
is used to get the current value of a reference. The above example uses
@
to get the current value of an atom, but @
can
be applied to other things such as future
s, delay
s, promises
s etc. to
force computation and potentially block.
Note that @
is not available in edn.
^
(and #^
) - Metadata^
is the metadata marker. Metadata is a map of values (with shorthand option)
that can be attached to various forms in Clojure. This provides extra information
for these forms and can be used for documentation, compilation warnings,
typehints, and other features.
user=> (def ^{:debug true} five 5) ; meta map with single boolean value
#'user/five
We can access the metadata by the meta
function which should be executed
against the declaration itself (rather than the returned value):
user=> (def ^{:debug true} five 5)
#'user/five
user=> (meta #'five)
{:ns #<Namespace user>, :name five, :column 1, :debug true, :line 1, :file "NO_SOURCE_PATH"}
As we have a single value here, we can use a shorthand notation for declaring
the metadata ^:name
which is useful for flags, as the value will be set to true.
user=> (def ^:debug five 5)
#'user/five
user=> (meta #'five)
{:ns #<Namespace user>, :name five, :column 1, :debug true, :line 1, :file "NO_SOURCE_PATH"}
Another use of ^
is for type hints. These are used to tell the compiler what
type the value will be and allow it to perform type specific optimizations
thus potentially making resultant code faster:
user=> (def ^Integer five 5)
#'user/five
user=> (meta #'five)
{:ns #<Namespace user>, :name five, :column 1, :line 1, :file "NO_SOURCE_PATH", :tag java.lang.Integer}
We can see in that example the :tag
property is set.
You can also stack the shorthand notations:
user=> (def ^Integer ^:debug ^:private five 5)
#'user/five
user=> (meta #'five)
{:ns #<Namespace user>, :name five, :column 1, :private true, :debug true, :line 1, :file "NO_SOURCE_PATH", :tag java.lang.Integer}
Originally, meta was declared with #^
, which is now deprecated (but still works). Later, this was simplified to just ^
and that is what you will see in most Clojure, but occasionally you will encounter the #^
syntax in older code.
Note that metadata is available in edn, but type hints are not.
'
- QuoteQuoting is used to indicate that the next form should be read but not evaluated.
The reader expands '
into a call to the quote
special form.
user=> (1 3 4) ; fails as it tries to invoke 1 as a function
Execution error (ClassCastException) at myproject.person-names/eval230 (REPL:1).
class java.lang.Long cannot be cast to class clojure.lang.IFn
user=> '(1 3 4) ; quote
(1 3 4)
user=> (quote (1 2 3)) ; using the longer quote method
(1 2 3)
user=>
;
- Comment;
starts a line comment and ignores all input from its starting point to the end of the
line.
user=> (def x "x") ; this is a comment
#'user/x
user=> ; this is a comment too
<returns nothing>
It is common in Clojure to use multiple semicolons for readability or emphasis, but these are all the same to Clojure
;; This is probably more important than
; this
:
- Keyword:
is the indicator for a keyword. Keywords are often used as keys in maps and
they provide faster comparisons and lower memory overhead than strings (because instances are cached and reused).
user=> (type :test)
clojure.lang.Keyword
Alternatively you can use the keyword
function to create a keyword from a string
user=> (keyword "test")
:test
Keywords can also be invoked as functions to look themselves up as a key in a map:
user=> (def my-map {:one 1 :two 2})
#'user/my-map
user=> (:one my-map) ; get the value for :one by invoking it as function
1
user=> (:three my-map) ; it can safely check for missing keys
nil
user=> (:three my-map 3) ; it can return a default if specified
3
user => (get my-map :three 3) ; same as above, but using get
3
::
- Auto-resolved keyword::
is used to auto-resolve a keyword in the current namespace. If no qualifier
is specified, it will auto-resolve to the current namespace. If a qualifier is
specified, it may use aliases in the current namespace:
user=> :my-keyword
:my-keyword
user=> ::my-keyword
:user/my-keyword
user=> (= ::my-keyword :my-keyword)
false
This is useful when creating macros. If you want to ensure that a macro that calls
another function in the macro namespace correctly expands to call the function,
you could use ::my-function
to refer to the fully qualified name.
Note that ::
is not available in edn.
#:
and #::
- Namespace Map SyntaxNamespace map syntax was added in Clojure 1.9 and is used to specify a default namespace context when keys or symbols in a map where they share a common namespace.
The #:ns
syntax specifies a fully-qualified namespace map prefix n alias
in the namespace map prefix with, where ns is the name of a namespace and the prefix
precedes the opening brace {
of the map.
For example, the following map literal with namespace syntax:
#:person{:first "Han"
:last "Solo"
:ship #:ship{:name "Millennium Falcon"
:model "YT-1300f light freighter"}}
is read as:
{:person/first "Han"
:person/last "Solo"
:person/ship {:ship/name "Millennium Falcon"
:ship/model "YT-1300f light freighter"}}
Note that these maps represent the identical object - these are just alternate syntaxes.
#::
can be used to auto-resolve the namespace of keyword or symbol keys
in a map using the current namespace.
These two examples are equivalent:
user=> (keys {:user/a 1, :user/b 2})
(:user/a :user/b)
user=> (keys #::{:a 1, :b 2})
(:user/a :user/b)
Similar to autoresolved keywords,
you can also use #::alias
to auto-resolve with a namespace alias defined in
the ns
form:
(ns rebel.core
(:require
[rebel.person :as p]
[rebel.ship :as s] ))
#::p{:first "Han"
:last "Solo"
:ship #::s{:name "Millennium Falcon"
:model "YT-1300f light freighter"}}
is read the same as:
{:rebel.person/first "Han"
:rebel.person/last "Solo"
:rebel.person/ship {:rebel.ship/name "Millennium Falcon"
:rebel.ship/model "YT-1300f light freighter"}}
/
- Namespace separator/
can be the division function clojure.core//
, but can also act as a
separator in a symbol name to separate a symbol’s name and namespace qualifier, e.g. my-namespace/utils
. Namespace qualifiers can thus prevent naming collisions
for simple names.
\
- Character literal\
indicates a literal character as in:
user=> (str \h \i)
"hi"
There are also a small number of special characters to name special ASCII characters: \newline
, \space
, \tab
, \formfeed
, \backspace
, and \return
.
The \
can also be followed by a Unicode literal of the form \uNNNN
. For example, \u03A9
is the literal for Ω.
$
- Inner class referenceUsed to reference inner classes and interfaces in Java. Separates the container class name and the inner class name.
(import (basex.core BaseXClient$EventNotifier)
(defn- build-notifier [notifier-action]
(reify BaseXClient$EventNotifier
(notify [this value]
(notifier-action value))))
EventNotifier
is an inner interface of the BaseXClient
class which is an
imported Java class
->
, ->>
, some->
, cond->
, as->
etc. - Threading macrosThese are threading macros. Please refer to Official Clojure Documentation
`
- Syntax quote`
is the syntax quote. Syntax quote is similar to quoting (to delay
evaluation) but has some additional effects.
Basic syntax quote may look similar to normal quoting:
user=> (1 2 3)
Execution error (ClassCastException) at myproject.person-names/eval232 (REPL:1).
class java.lang.Long cannot be cast to class clojure.lang.IFn
user=> `(1 2 3)
(1 2 3)
However, symbols used within a syntax quote are fully resolved with respect to the current namespace:
user=> (def five 5)
#'user/five
user=> `five
user/five
Syntax quote is most used as a "template" mechanism within macros. We can write one now:
user=> (defmacro debug [body]
#_=> `(let [val# ~body]
#_=> (println "DEBUG: " val#)
#_=> val#))
#'user/debug
user=> (debug (+ 2 2))
DEBUG: 4
4
Macros are functions invoked by the compiler with code as data. They are expected
to return code (as data) that can be further compiled and evaluated.
This macro takes a single body expression and returns a let
form that will
evaluate the body, print its value, and then return the value. Here the syntax
quote creates a list, but does not evaluate it. That list is actually code.
~
- UnquoteSee `
for additional information.
~
is unquote. That is within a syntax quoted `
form ~
will unquote
the associated symbol, i.e. evaluate it in the current context:
user=> (def five 5) ; create a named var with the value 5
#'user/five
user=> five ; the symbol five is evaluated to its value
5
user=> `five ; syntax quoting five will avoid evaluating the symbol, and fully resolve it
user/five
user=> `~five ; within a syntax quoted block, ~ will turn evaluation back on just for the next form
5
Syntax quoting and unquote are essential tools for writing macros, which are functions invoked during compilation that take code and return code.
~@
- Unquote splicing~@
is unquote-splicing. Where unquote (~
)
evaluates a form and places the result into the quoted result, ~@
expects the
evaluated value to be a collection and splices the contents of that
collection into the quoted result.
user=> (def three-and-four (list 3 4))
#'user/three-and-four
user=> `(1 ~three-and-four) ; evaluates `three-and-four` and places it in the result
(1 (3 4))
user=> `(1 ~@three-and-four) ; evaluates `three-and-four` and places its contents in the result
(1 3 4)
Again, this is a powerful tool for writing macros.
<symbol>#
- GensymA #
at the end of a symbol is used to automatically generate a new symbol.
This is useful inside macros to keep macro specifics from leaking into the
userspace. A regular let
will fail in a macro definition:
user=> (defmacro m [] `(let [x 1] x))
#'user/m
user=> (m)
Syntax error macroexpanding clojure.core/let at (REPL:1:1).
myproject.person-names/x - failed: simple-symbol? at: [:bindings :form :local-symbol]
spec: :clojure.core.specs.alpha/local-name
myproject.person-names/x - failed: vector? at: [:bindings :form :seq-destructure]
spec: :clojure.core.specs.alpha/seq-binding-form
myproject.person-names/x - failed: map? at: [:bindings :form :map-destructure]
spec: :clojure.core.specs.alpha/map-bindings
myproject.person-names/x - failed: map? at: [:bindings :form :map-destructure]
spec: :clojure.core.specs.alpha/map-special-binding
This is because symbols inside a syntax quote are fully resolved, including the
local binding x
here.
Instead you can append #
to the end of the variable name and let Clojure
generate a unique (unqualified) symbol:
user=> (defmacro m [] `(let [x# 1] x#))
#'user/m
user=> (m)
1
user=>
Importantly, every time a particular x#
is used within a single syntax quote, the same generated name will be used.
If we expand this macro, we can see the gensym
'd name:
user=> (macroexpand '(m))
(let* [x__681__auto__ 1] x__681__auto__)
#?
- Reader conditionalReader conditionals are designed to allow different dialects of Clojure
to share common code. The reader conditional behaves similarly to a traditional
cond
. The syntax for usage is #?
and looks like this:
#?(:clj (Clojure expression)
:cljs (ClojureScript expression)
:cljr (Clojure CLR expression)
:default (fallthrough expression))
#?@
- Splicing Reader conditionalThe syntax for a splicing reader conditional is #?@
. It is used to splice
lists into the containing form. So the Clojure reader would read this:
(defn build-list []
(list #?@(:clj [5 6 7 8]
:cljs [1 2 3 4])))
as this:
(defn build-list []
(list 5 6 7 8))
*var-name*
- "Earmuffs"Earmuffs (a pair of asterisk bookending var names) is a naming convention in many LISPs used to denote special vars. Most commonly in Clojure this is used to denote dynamic vars, i.e. ones that can change depending on dynamic scope. The earmuffs act as a warning that "here be dragons" and to never assume the state of the var. Remember, this is a convention, not a rule.
Core Clojure examples include *out*
and *in*
which represent the standard in
and out streams for Clojure.
>!!
, <!!
, >!
, and <!
- core.async channel macrosThese symbols are channel operations in core.async
- a Clojure/ClojureScript library for channel based asynchronous programming
(specifically CSP - Communicating Sequential Processes).
If you imagine, for the sake of argument, a channel is a bit like a queue that things can put stuff on and take stuff off, then these symbols support that simple API.
>!!
and <!!
are blocking put and take respectively
>!
and <!
are, simply put and take
THe difference being the blocking version operate outside go
blocks and block
the thread they operate on.
user=> (def my-channel (chan 10)) ; create a channel
user=> (>!! my-channel "hello") ; put stuff on the channel
user=> (println (<!! my-channel)) ; take stuff off the channel
hello
The non-blocking versions need to be executed within a go
block, otherwise
they’ll throw an exception.
user=> (def c (chan))
#'user/c
user=> (>! c "nope")
AssertionError Assert failed: >! used not in (go ...) block
nil clojure.core.async/>! (async.clj:123)
While the difference between these is well outside the scope of this guide,
fundamentally the go
blocks operate and manage their own resources pausing
execution of code without blocking threads. This makes asynchronously executed
code appear to be synchronous, removing the pain of managing
asynchronous code from the code base.
<symbol>?
- Predicate SuffixPutting ?
at the end of a symbol is a naming convention common across
many languages that support special characters in their symbol names. It is
used to indicate that the thing is a predicate, i.e. that it poses a question.
For example, imagine using an API that dealt with buffer manipulation:
(def my-buffer (buffers/create-buffer [1 2 3]))
(buffers/empty my-buffer)
At a glance, how would you know if the function empty
in this case,
Returned true
if the passed in buffer was empty, or,
Cleared the buffer
While the author could have renamed empty
to is-empty
, the richness of
symbol naming in Clojure allows us to express intent more symbolically.
(def my-buffer (buffers/create-buffer [1 2 3]))
(buffers/empty? my-buffer)
false
This is simply a recommended convention, not a requirement.
<symbol>!
- Unsafe OperationsThe names of functions/macros that are not safe in STM transactions
should end with an exclamation mark (e.g reset!
).
You’ll most commonly see this appended to function names whose purpose is to mutate state, e.g. connecting to a data store, updating an atom or closing a file stream
user=> (def my-stateful-thing (atom 0))
#'user/my-stateful-thing
user=> (swap! my-stateful-thing inc)
1
user=> @my-stateful-thing
1
This is simply a recommended convention and not a requirement.
Note that the exclamation mark is often pronounced as bang.
_
- Unused argumentWhen you see the underscore character used as function arguments or in a let
binding,
_
is a common naming convention to indicate you won’t be using this argument.
This is an example using the add-watch
function that can be used to add
callback style behaviour when atoms change value. Imagine, given an atom, we
want to print the new value every time it changes:
(def value (atom 0))
(add-watch value nil (fn [_ _ _ new-value]
(println new-value))
(reset! value 6)
; prints 6
(reset! value 9)
; prints 9
add-watch
takes four arguments, but in our case we only really care about the
last argument - the new value of the atom so we use _
for the others.
,
- Whitespace characterIn Clojure, ,
is treated as whitespace, exactly the same as spaces, tabs, or newlines.
Commas are thus never required in literal collections, but are often used to enhance
readability:
user=>(def m {:a 1, :b 2, :c 3}
{:a 1, :b 2, :c 3}
#=
Reader eval#=
allows the reader to evaluate an arbitrary form during read time:
user=> (read-string "#=(+ 3 4)")
;;=> 7
Note that the read-time evaluation can also cause side-effects:
user=> (read-string "#=(println :foo)")
:foo
nil
Consequently, read-string
is not safe to call with unverified user input.
For a safe alternative, see clojure.edn/read-string
.
Note that #=
is not an officially supported feature of the reader, so you
shouldn’t rely on its presence in future versions of Clojure.
Many thanks to everyone who has contributed ideas and [the copious amounts of] spelling corrections (crikey I’m bad at speelingz - so thanks Michael R. Mayne, lobsang_ludd). I’ve tried to call out people who have specifically asked for things. Sorry if I’ve missed you.