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.

General

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

As in Lisp, code and data have the same syntax.

Clojure has a lot more syntactic sugar than Lisp, which makes it more complex to learn but easier to read.

Clojure supports functional programming, but does not encourage it to the extent that Lisp does.

Clojure supports lock-free concurrency with Software Transactional Memory.

Like many modern languages, Clojure is interoperable with Java and uses the JVM.

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.

Integers include decimal integers ( 255 ), octals numbers ( 012 ), hexadecimal numbers ( 0xff ) and radix numbers ( 2r1111 ), where the radix is an integer between 2 and 36, inclusive.

), octals numbers ( ), hexadecimal numbers ( ) and radix numbers ( ), where the radix is an integer between 2 and 36, inclusive. Floating point numbers include standard notation ( 3.1416 ) and scientific notation( 1.35e-12 ).

) and scientific notation( ). Ratios are "fractions" that are not equivalent to integers, such as 1/3 . They are not subject to roundoff error.

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

line two" . Inside a string, backslashed characters have the same meaning as in Java (for example,

indicates a newline).

Characters are written with a backslash, for example, \a. For nonprinting characters, use

ewline , \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.

Function calls are written as a list. The first element of a list is the name of a function, and the remaining elements are the arguments to the function, for example (max 23 92 17) .

Lists that don't represent function calls should usually be quoted.A list can be quoted with the syntax '(1 2 3) or (quote (1 2 3)) .

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.

As in other languages, the arguments to a function are evaluated, and these values are passed to the function

are evaluated, and these values are passed to the function The arguments to a special form are not evaluated, but are passed in "as is" to the special form, which decides when and whether to evaluate them. There are only a small number of special forms, and they are all important.

are not evaluated, but are passed in "as is" to the special form, which decides when and whether to evaluate them. There are only a small number of special forms, and they are all important. A macro takes its arguments unevaluated, and returns an expression to be evaluated in place of the call to the macro. Macros allow the programmer to "extend" the language.

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

+

*

?

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.

Vectors

A vector is a sequence of values enclosed in brackets.

A vector can be created with (vector args*) , or by writing the values in square brackets.

, or by writing the values in square brackets. To access an element by its position, use (nth vector index) or (nth vector index not-found) .

or . (contains? vector index) tests whether the integer index is within the range of legal indices of the vector .

tests whether the integer is within the range of legal indices of the . (rseq vector) returns, in constant time, a sequence of the items in the vector, in reverse.

returns, in constant time, a sequence of the items in the vector, in reverse. (pop vector) returns a vector without the last element.

returns a vector without the last element. (subvec vector start end) returns a view of the vector from start up to but not including end .

returns a view of the vector from up to but not including . (replace map vector) replaces the keys found in the vector with the corresponding values.

replaces the keys found in the vector with the corresponding values. (assoc vector index value) returns a new vector with the index-th location set to the value.

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

Records

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.

To define a record type: (defrecord TypeName [fieldnames*]) . Example: (defrecord Tree [value left right]) . Don't use keywords as field names.

. Example: Don't use keywords as field names. To create an instance: (Typename. args*) . Example: (def animals (Tree. "Water animal?" "frog" "horse")) .

. Example: . To refer to a field, use the keyword version of the field name as a function: for example, (:left animals) .

Structs

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

Arithmetic

+ Returns the sum of its arguments; (+) returns 0

Returns the sum of its arguments; returns 0 - Subtracts the rest of the numbers from the first number

Subtracts the rest of the numbers from the first number * Returns the product of its arguments; (*) returns 1.

Returns the product of its arguments; returns 1. / Divides the rest of the numbers into the first number If operands are integers, result is a ratio If only one number, returns its inverse

Divides the rest of the numbers into the first number quot Returns the quot ient of integer division of the first number by the rest of the numbers

Returns the ient of integer division of the first number by the rest of the numbers rem Remainder of dividing the first number by the second

Remainder of dividing the first number by the second mod Modulus of first and second number; truncates toward negative infinity

Modulus of first and second number; truncates toward negative infinity inc Returns a number one greater than its argument

Returns a number one greater than its argument dec Returns a number one less than its argument

Returns a number one less than its argument max Returns the largest of its arguments

Returns the largest of its arguments min Returns the smallest of its arguments

Returns the smallest of its arguments int Truncates a float to an integer, or returns the integer value of a character

Truncates a float to an integer, or returns the integer value of a character float Converts an integer to a float

Converts an integer to a float Not provided: abs

Numeric comparisons

== Returns true if numeric arguments all have the same value, otherwise false

Returns true if numeric arguments all have the same value, otherwise false not= Same as (not (= obj1 obj2))

Same as < Returns true if numeric arguments are in monotonically increasing order

Returns true if numeric arguments are in monotonically increasing order > Returns true if numeric arguments are in monotonically decreasing order, otherwise false

Returns true if numeric arguments are in monotonically decreasing order, otherwise false <= Returns true if numeric arguments are in monotonically non-decreasing order, otherwise false

Returns true if numeric arguments are in monotonically non-decreasing order, otherwise false >= Returns true if numeric arguments are in monotonically non-increasing order, otherwise false

Tests

nil? Returns true if the argument is nil , false otherwise

Returns true if the argument is , false otherwise true? Returns true if the argument is true , false otherwise

Returns true if the argument is , false otherwise false? Returns true if the argument is false , false otherwise

Returns true if the argument is , false otherwise identical? Tests if the two arguments are the same object

Tests if the two arguments are the same object zero? Returns true if the argument is zero, else false

Returns true if the argument is zero, else false pos? Returns true if the argument is greater than zero

Returns true if the argument is greater than zero neg? Returns true if the argument is less than zero, else false

Returns true if the argument is less than zero, else false even? Returns true if the argument is even, throws an exception if the argument is not an integer

Returns true if the argument is even, throws an exception if the argument is not an integer odd? Returns true if n is odd, throws an exception if the argument is not an integer

Returns true if n is odd, throws an exception if the argument is not an integer coll? Returns true if the argument is a collection type (a sequence, list, vector, set, or map)

Returns true if the argument is a collection type (a sequence, list, vector, set, or map) vector? Return true if the argument is a vector

Return true if the argument is a vector list? Returns true if the argument is a list

Returns true if the argument is a list map? Return true if the argument is a map

Return true if the argument is a map set? Returns true if the argument is a set

Returns true if the argument is a set string? Returns true if the argument is a string

Returns true if the argument is a string contains? Returns true if key is present in the given collection, else false

Returns true if key is present in the given collection, else false distinct? Returns true if no two of the arguments are =

Returns true if no two of the arguments are = empty? Returns true if the collection argument has no items - same as (not (seq coll)) Use the idiom (seq x) rather than (not (empty? x))

Returns true if the collection argument has no items - same as

Logic

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

(and arg *) Returns nil or false if they occur as an argument, else returns the last argument (macro, not function)

Returns nil or false if they occur as an argument, else returns the last argument (macro, not function) (or arg *) Returns the first value that isn't false or nil, or returns false or nil

Returns the first value that isn't false or nil, or returns false or nil (not arg) Returns true if the argument is false, and vice versa

Higher-order functions

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

(map function sequence) Applies the single-parameter function to each value in the sequence , returning a list of the results.

Applies the single-parameter to each value in the , returning a list of the results. (filter test sequence) Applies the test to each value in the sequence and returns a list of the values that pass the test.

Applies the to each value in the and returns a list of the values that pass the test. (complement predicate) Returns a predicate whose result (when applied) is the negation of the result of predicate .

Returns a predicate whose result (when applied) is the negation of the result of . (reduce function value? collection) Applies the two-parameter function to the value? and the first element of the sequence (if value? is present), else to the first two elements of the sequence; applies the function to the result and the next element in the list, recursively.

Applies the two-parameter function to the and the first element of the sequence (if is present), else to the first two elements of the sequence; applies the function to the result and the next element in the list, recursively. (every? predicate collection) Returns true if the first argument (a predicate) is logically true for every element in the second argument (a collection), else false

Returns true if the first argument (a predicate) is logically true for every element in the second argument (a collection), else false (not-every? predicate collection) Returns false if the first argument (a predicate) is logically true for every element in the second argument (a collection), else true

Returns false if the first argument (a predicate) is logically true for every element in the second argument (a collection), else true (some predicate collection) Returns the first value in the second argument (a collection) that satisfies the first argument (a predicate)

Returns the first value in the second argument (a collection) that satisfies the first argument (a predicate) (not-any? predicate collection) Returns true if no value in the second argument (a collection) satisfies the first argument (a predicate)

Returns true if no value in the second argument (a collection) satisfies the first argument (a predicate) Not provided: zip

List comprehensions

(for [name sequence modifiers? ...] body_expression) Sets the name to each value in the sequence (rightmost sequences varying fastest), omitting those for which the optional :when or :while test is false, evaluates the expression using this value, and returns a lazy list of the results. A sequence_expression is a name followed by a collection, followed by zero or more modifiers. Allowable modifiers are :when test , :while test , and :let [name expression ...] .

Sets the to each value in the (rightmost sequences varying fastest), omitting those for which the optional or test is false, evaluates the using this value, and returns a lazy list of the results.

*in* A java.io.Reader object representing standard input for read operation

A object representing standard input for read operation *out* A java.io.Writer object representing standard output for print operations

A object representing standard output for print operations *err* A java.io.Writer object representing standard error for print operations

A object representing standard error for print operations print Prints the object(s) to the output stream that is the current value of *out*

Prints the object(s) to the output stream that is the current value of printf Prints formatted output, as per format

Prints formatted output, as per format println Same as print followed by (newline)

Same as followed by pr Prints the object(s) to the output stream that is the current value of *out*

Prints the object(s) to the output stream that is the current value of prn Same as pr followed by (newline). Observes *flush-on-newline*

Same as followed by (newline). Observes newline Writes a newline to the output stream that is the current value of *out*

Writes a newline to the output stream that is the current value of read-line Reads the next line from stream that is the current value of *in*

Reads the next line from stream that is the current value of read Reads an object from the specified stream (default *in* )

Reads an object from the specified stream (default ) slurp Reads the file into a string and returns it

Reads the file into a string and returns it spit Opposite of slurp . Opens file with writer, writes content, then closes it

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 arguments to a macro are not evaluated

The result returned by the macro must be Clojure code

Calls to the macro are executed at compile time, and the call is replaced by the result that is returned.

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

(defmacro triple-do [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 ")) .

Templates

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,

(defmacro triple-do [form] `(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)) )

(macroexpand '(average-macro 3 5))

(let* [avg__99__auto__ (clojure.core/+ 3 5)] (clojure.core// avg__99__auto__ 2))

Software Transactional Memory

References

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.

(ref initial-value) creates a reference, which is typically associated with a variable: (def ref-variable (ref initial-value)) .

creates a reference, which is typically associated with a variable: . (deref ref-variable) returns the value associated with ref-variable .

returns the value associated with . @ref-variable is syntactic sugar for (deref ref-variable).

(dosync expression ... expression)

expressions

(ref-set ref-variable new-value) to associate the ref-variable with the new-value .

to associate the with the . (alter ref-variable function more-args) calls the function with the value of ref-variable as the first argument and more-args as the remaining arguments, sets ref-variable , and returns the new value.

Atoms

atom

(atom initial-value) creates an atom, which is typically associated with a variable: (def atom-name (atom initial-value)) .

creates an atom, which is typically associated with a variable: . (deref atom-name) and @ atom-name each return the value associated with atom-name .

(reset! atom-name new-value) will change the value associated with atom-name , and return the new-value .

will change the value associated with , and return the . (swap! atom-name function more-args) calls the function with the value of atom-name as the first argument and more-args as the remaining arguments, sets atom-name , and returns the new value.



Agents

agent

(agent initial-state) creates an agent from a thread pool and starts it running concurrently.



creates an agent from a thread pool and starts it running concurrently. Typical use: (def agent-name (agent initial-state))

(send agent-name update-function more-args ) sends the update-function to the named agent, which will then call the function with its data as the first argument and more-args as the remaining arguments. Immediately returns the named agent as its value--or, if done within a transaction, the send is postponed until the transaction completes.

(deref agent-name)

@

agent-name

(await agent-name-1 ... agent-name-N) blocks until all agents complete, and it could block forever.

blocks until all agents complete, and it could block forever. (await-for timeout-millis agent-name-1 ... agent-name-N) blocks until all agents complete or until it times out; it returns nil if it times out, otherwise non-nil.

Errors in agents

(agent initial-state :validator validator-function)

validator-function

validator-function

(agent-errors agent-name) will return a sequence of errors encountered by the agent.

will return a sequence of errors encountered by the agent. (clear-agent-errors agent-name ) will make the agent useable again.

will make the agent useable again. (set-validator! agent-name validator-fn) adds a validator to an existing agent.

adds a validator to an existing agent.



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.