A Concise Guide to Clojure
Copyright ©2011, David Matuszek

The original version of this page was based on http://lifeofaprogrammergeek.blogspot.com/2009/03/learning-clojure-and-emacs.html.


Clojure is a modern variant of Lisp-1. The following comparisons are to the "original" Lisp.

To run Clojure, enter: java -jar clojure-1.8.0.jar (substitute your version number, if different). To load in and execute a file, enter (load-file "filename")

Basic data types

Numbers: Clojure has integers, floating point numbers, and ratios.

Atoms (variables): Names for values. Clojure allows most non-alphanumeric characters in names (but not parentheses, brackets, or braces).

Important atoms: true, false, and nil. In a condition, nil behaves like false; but nil is not equal to an empty list, ().

Strings are enclosed in double quotes, and can contain escaped characters: "hello", "line one\nline two". Inside a string, backslashed characters have the same meaning as in Java (for example, \n indicates a newline).

Characters are written with a backslash, for example, \a.For nonprinting characters, use \newline, \space, \tab, \formfeed, \backspace, and \return.

Regular expressions are written as a hash character in front of a string: #"[a-z]+". Backslashes do not need to be doubled.

Keywords are not reserved words (like while in Java), but are like "atoms" in Prolog or Erlang. A keyword begins with a colon (:foo) and stands for itself. Keywords are often used as keys in maps.

A list is a sequence of values, separated by whitespace (including commas) and enclosed in parentheses.

A vector is a sequence of values enclosed in brackets, for example [1 2 "buckle my shoe"], or equivalently, (vector 1 2 "buckle my shoe"). Elements of a vector are separated by whitespace, including commas. Vectors are used to enclose the formal parameters of a function.

A map or hash is a sequence of key/value pairs, enclosed in braces, for example, {:ace 1, :deuce 2, "trey" 3}. Elements are separated by whitespace or commas; it is helpful to use commas between key/value pairs.

A set is a pound sign (#) followed sequence of values enclosed in braces, for example #{a b c}.

Clojure has functions, special forms, and macros.

Functions are first-class objects. That is, a function is a value, and can be treated like other kinds of values. Functions can be assigned to variables, passed as parameters to functions, returned as the result of functions, and kept in collections, and there are operations that act on functions. Special forms and macros are not first-class objects.

(type x) will return the type of x (as a java.lang.Class).

Comments begin with a semicolon and extend to the end of the line.

Defining and calling functions

The syntax of a named function is: (defn function_name [arguments] expressions). The value of the function is the value of the last expression evaluated.

Parameters may be "deconstructed" (this is akin to pattern matching). For example, if an argument must have the form [a b], the formal parameter may be [x y].

A function may be defined to evaluate different expressions based on the number of arguments. The syntax is (defn function_name ([arguments] expressions) ... ([arguments] expressions)), where each list of arguments is a different length.

A function may be defined to accept an arbitrary number of arguments. The syntax is (defn function_name [arguments & last-argument] expressions). The arguments before the ampersand are as usual; the one last-argument is given to the function as a list of all remaining arguments.

A documentation string may be placed immediately before the vector of arguments. The function (doc function-name) will print out this documentation string, along with other information about the function. doc can be used with built-in functions.

The syntax of a function call is (function_name arguments). The name of the function being called is the first thing inside the parentheses.

The syntax of an anonymous function, or lambda, is (fn [arguments] expressions). This syntax can be used in place of a function name; for example, ((fn [lst] (first lst)) my-list) is equivalent to (first my-list).

Built-in functions

Notation: A + suffix on an argument means "one or more"; a * suffix means "zero or more"; and a ? suffix means "zero or one", that is, optional.

Absolutely fundamental functions

(first sequence)
Returns the first element of a nonempty sequence, or nil if the sequence is empty. For "unordered" collection types, such as sets, some element will be returned, based on how the collection is stored in memory.
(rest sequence)
Returns a list containing all the elements of the given sequence but the first, or () if the given sequence is empty.
(cons value sequence)
Returns a new list created by adding the value as the first element of the given sequence.
(conj sequence value...)
Returns a new sequence created by adding the values to the given sequence. Values will be added to the beginning of a list or to the end of a vector.
(empty? sequence)
Returns true if the sequence is empty, and false otherwise.
(= value1 value2)
Tests whether two values are equal. Works for just about anything except functions.

Additional functions

(concat sequence*)
Concatenates the sequences into a single list. Example: (concat [1 2 3] [5 6] [9]) ;=> (1 2 3 5 6 9)
(apply function arg* sequence)
Equivalent to (function (concat arg* sequence)). Example: (apply + 1000 100 '(1 2 3)) ;=> 1106
(frequencies sequence)
Returns a map from distinct items in sequence to the number of times they appear.
(into empty-sequence sequence)
Converts the sequence into the type given by the empty-sequence.

Macros and special forms

Macros and special forms differ from functions in that the arguments are not evaluated before the special form is called. They can then decide whether, when, and how often to evaluate the arguments. There is little difference from the user's point of view; but new macros can be written by the programmer.

(quote argument)
Returns its argument, unevaluated.
(def name expression)
Defines the name to have the value of the expression, in the current namespace. Clojure is single-assignment: Names cannot be reassigned to have a different value (except in the REPL).
(if test thenPart elsePart?)
The test is evaluated; if it is a "true" value, the thenPart is evaluated; if it is a "false" value and there is an elsePart, the elsePart is evaluated. This special form is convenient for simple tests, but for multiway tests, cond is preferable.
(when test expression ... expression)
If the test evaluates to a true value, the expressions are evaluated, and the value of the last expression is returned.
(cond test expression ... test expression)
The tests are evaluated in order, until one is found that results in a "true" value; then the corresponding expression is evaluated and returned as the value of the cond. If no test is true, nil is returned.
(do exprs*)
Evaluates the expressions in order and returns the value of the last. If no expressions are supplied, returns nil.
(let [name value ... name value] expressions*)
Defines local names, evaluates the corresponding values, and binds them to the names. The names are then available in the expressions, which are evaluated in order. The value of the let is the value of the last expression evaluated.
(letfn [(fname [parameters] expressions) ... (fname [parameters] expressions)] expressions*)
Defines local functions fnames, which are then available in the expressions, which are evaluated in order. The value of the letfn is the value of the last expression evaluated. The local functions may also be defined with the syntax (fname ([parameters] expressions) ... ([parameters] expressions)).
(throw expression)
The expression must evaluate to some kind of Throwable, which is then thrown.
(try expressions* catch-clauses* finally-clause?)
Evaluates the expressions. If no exceptions occur and the finally-clause is omitted, the result of the last expression is returned. If an exception occurs, then the corresponding catch-clause, with the syntax (catch ExceptionName name expressions*), is evaluated and returned. If there is a finally-clause, with the syntax (finally expressions*), then whether or not an exception occurs, it will be evaluated for its side effects.
(recur expressions*)
Performs a recursive call from the tail position (see Tail Recursion), with the exact (not arbitrary) number of arguments.
(loop [bindings*] expressions*)
Like recur, but the recursion point is at the top of the loop.

Functions for specific data types

Characters and strings

Clojure depends on Java for almost all character and string manipulations, for example, (.toUpperCase string) and (Character/toUpperCase char).

(str arguments*)
Converts any number of arguments into strings and concatenates them; ignores any nil argument. Also useful if the arguments are already strings.
(read-string string)
Reads one object from the given string; returns nil if the string is empty.


A vector is a sequence of values enclosed in brackets.

Maps (also known as hashes)

A map or hash is a sequence of key/value pairs, enclosed in braces. The primary operation is searching a map for a given key, and returning its value. This can be done by using either the map or a key as a function, or the function get.

(map key)
(key map)
(get map key)
(get map key default-value)
Each of these looks up the key in the map, and returns the associated value. If the key does not occur in the map, the first and third forms return nil, while the third form gives an error and the fourth form returns the default-value.
(keys map)
Returns a list of the keys.
(vals map)
Returns a list of the values.
(contains? map key)
Tests whether the key is in the map.
(assoc map key value)
Returns a new map like the given map, but with the added or updated key/value pair
(dissoc map keys)
Returns a new map like the given map, but with the matching key/value pairs removed; keys not in map are ignored
(merge maps)
Combine multiple maps; if a key occurs in more than one map, the rightmost key/value is retained


A record definition is something like a Java class. It acts as a map but, because the "fields" are predefined, it can be more efficient.


Records are newer and better than structs. Don't use structs.


Numeric comparisons



These functions treat nil and false as being false, everything else (including the empty list) count as true.

Higher-order functions

A higher-order function is one that accepts a function as an argument, returns a function as its result, or both.

List comprehensions


Defining macros

Metaprogramming is using a program to write a program (or parts of a program). Metaprogramming is especially in a homoiconic language, that is, a language in which code and data have the same representation. Clojure is homoiconic.

A Clojure macro resembles a function, with these important differences:

The following examples are from Practical Clojure by Luke VanderHart and Stuart Sierra.

(defmacro triple-do [form] ; makes three copies of the form
    (list 'do form form form) )

The call (triple-do (print "Hello ")) prints "Hello Hello Hello " and returns nil.

The forms macroexpand and macroexpand-1 each take a quoted macro call, and return the expanded macro; macroexpand-1 expands a recursive macro only once. For example, (macroexpand '(triple-do (print "Hello "))) returns (do (print "Hello ") (print "Hello ") (print "Hello ")).


The usual list operations are enough to create code, but can be very cumbersome. To make this easier, Clojure supplies a special kind of quote, `, called a syntax-quote. What makes this special is that within the quoted code, things can be unquoted with ~. For example,

    `(do ~form ~form ~form) )

If s is a sequence, ~s will be put into the template as the entire sequence. Sometimes it is desirable to instead put the individual elements of the sequence into the template. This can be done with the splicing unquote, ~@ -- for example, ~@s. If this doesn't make sense now, come back to it when you get unwanted parentheses in your expanded macro.

To avoid name conflicts with the code that uses a macro, it is illegal to create and bind local symbols in a macro, unless you end the symbol name with a # character. This tells Clojure to replace the symbol name with some generated name that is guaranteed to be unique. For example, if you define

(defmacro average-macro [a b]
  `(let [avg# (+ ~a ~b)] (/ avg# 2)) )
then (macroexpand '(average-macro 3 5)) will return something like (let* [avg__99__auto__ (clojure.core/+ 3 5)] (clojure.core// avg__99__auto__ 2)).

Software Transactional Memory


A set of actions is atomic if, from the point of view of other threads, the actions have either all happened, or none of them have happened. This is essentially what a "synchronized" block in Java is trying to accomplish, and the purpose is to prevent data corruption.

A ref is a mutable reference to an immutable value.

Reference variables can only be updated in a transaction, expressed as (dosync expression ... expression). A transaction is atomic. Within the transaction, some of the expressions may be:
A transaction may be attempted multiple times (it will fail if the variables being modified have been changed by another thread while the transaction is being attempted). Hence the actions in a transaction should be completely free of side effects, and return a purely functional transformation of the ref value.


An atom holds a single value.
Updating an atom does not require the use of a transaction.
As with a transaction, updating an atom should be free of side effects and a purely functional transformation of the value.


An agent is a separate thread that holds data. The data can be modified by sending a function to the agent.

An agent is created with an initial value:
You can send an agent a function to update its state:
You can check the current state of an agent with (deref agent-name) or @agent-name.

You can wait for agents to complete:

Errors in agents

An agent can be created with (agent initial-state :validator validator-function). When the state changes, the validator-function is called; if the new state is unacceptable, the validator-function returns false or throws an exception. If bad data is sent to an agent, all attempts to query the agent will give an error.

Interoperability with Java

Clojure can use Java objects, methods, and fields. This includes Java's collections data types, although Clojure's datatypes are preferable because they are immutable and persistent. Possibly the best use of Java in Clojure is to make Swing GUIs.

(import import-lists*)
Imports the named Java classes. Example: (import '(java.awt.Color) '(java.awt.Point)).
Only classes can be imported, not entire packages; there is no equivalent of import java.util.*;
All of java.lang is implicitly imported, along with everything in clojure.core.
(new JavaClassName args*)
(JavaClassName. args*) ;
syntactic sugar for the above--notice the period, it's important!
Creates and returns a new Java object of the specified class. Examples: (def rnd (new java.util.Random)), (def c (java.awt.Color. 255 128 0))
(. JavaObject methodName args*)
(.methodName JavaObject args*)
Calls the Java object's method with the supplied arguments. Examples: (. rnd nextInt 10), (.nextInt rnd 10).
(. JavaObject fieldName)
Returns the value in the named field of the Java object. Example: After (def p (new java.awt.Point 20 40)), (. p x) will return 20.
(JavaClass/staticMethodName args*)
Calls the static method of the class. Example: (System/currentTimeMillis).
Returns the value in the static field of the class. Example: (java.awt.Color/CYAN).
doto(JavaInstanceOrClass methodCalls*)
Uses the Java object or class as the receiver for any number of method calls. Example: (doto (new java.util.HashMap) (.put "a" 1) (.put "b" 2)).
(proxy [Class? Interfaces*] [constructorArgs*] functions*)
Creates a Clojure class to do the work that would be done by a Java class in Java. The optional Class? parameter names the superclass (and if omitted, defaults to Object). If the class's constructor requires parameters, those are provided in the second vector, otherwise the second vector is emtpy, []. The functions are usual Clojure functions (omitting the defn), and have the form (name [params*] body) or (name ([params*] body) ([params+] body) ...). For example,
(. convert-button
    (proxy [ActionListener] []
      (actionPerformed [evt]
        (let [c (Double/parseDouble (. temp-text (getText)))]
          (. fahrenheit-label
            (setText (str (+ 32 (* 1.8 c)) " Fahrenheit"))))))))
There are also functions for dealing with Java arrays, and for treating Java methods as first-class objects. These are not covered here.