Learning Clojure
Learning Clojure
Learning Clojure
#clojure
Table of Contents
About 1
Remarks 2
Versions 2
Examples 3
Option 1: Leiningen 3
Linux 3
OS X 3
Windows 4
Option 3: Boot 4
Chapter 2: Atom 7
Introduction 7
Examples 7
Define an atom 7
Chapter 3: clj-time 9
Introduction 9
Examples 9
Getting Day Month Year Hour Minute Second from your date-time 9
Examples 12
Destructuring a vector 12
Destructuring a map 12
Destructuring params of a fn 14
Overview 14
Tips: 15
Chapter 5: clojure.core 17
Introduction 17
Examples 17
Chapter 6: clojure.spec 19
Syntax 19
Remarks 19
Examples 19
Registering a spec 20
Record specs 21
Map specs 21
Collections 22
Sequences 24
Chapter 7: clojure.test 25
Examples 25
is 25
are 26
Syntax 28
Examples 28
Collections 28
Lists 28
Sequences 31
Vectors 35
Sets 39
Maps 41
Chapter 9: core.async 47
Examples 47
Closing channels 48
Introduction 51
Examples 51
Function Evaluation 51
Pretty Print 51
Examples 53
Overview 53
Notes: 53
Examples 54
Defining Functions 54
Arity 55
Supported Syntax 56
Examples 58
Web Servers 59
databases 59
miscellaneous 59
Syntax 61
Remarks 61
Examples 61
Syntax 63
Remarks 63
Examples 63
Examples 65
Remarks 66
Examples 66
Matching Literals 66
Matching a Vector 66
Matching a Map 66
Introduction 68
Remarks 68
Examples 68
Math Examples 68
Examples 69
Light Table 69
Emacs 70
Atom 70
Spacemacs + CIDER 71
Vim 72
Introduction 73
Examples 73
Thread as (as->) 73
Introduction 75
Remarks 75
Examples 75
Applying transducers 76
Creating/Using Transducers 76
Examples 78
Truthiness 78
Booleans 78
Syntax 79
Remarks 79
Examples 79
Types of Variables 79
Credits 80
About
You can share this PDF with anyone you feel could benefit from it, downloaded the latest version
from: clojure
It is an unofficial and free clojure ebook created for educational purposes. All the content is
extracted from Stack Overflow Documentation, which is written by many hardworking individuals at
Stack Overflow. It is neither affiliated with Stack Overflow nor official clojure.
The content is released under Creative Commons BY-SA, and the list of contributors to each
chapter are provided in the credits section at the end of this book. Images may be copyright of
their respective owners unless otherwise specified. All trademarks and registered trademarks are
the property of their respective company owners.
Use the content presented in this book at your own risk; it is not guaranteed to be correct nor
accurate, please send your feedback and corrections to info@zzzprojects.com
https://riptutorial.com/ 1
Chapter 1: Getting started with clojure
Remarks
Its features support the functional style of programming with first-class functions and immutable
values by default. Using reassignable variables is not as easy in Clojure as in many mainstream
languages, since variables have to be created and updated like container objects. This
encourages use of pure values that will stay the way they were at the moment they were last seen.
This typically makes code much more predictable, testable and concurrency-capable. This works
for collections too, since Clojure's built-in data structures are persistent.
For performance, Clojure supports type-hinting to eliminate unnecessary reflection where possible.
Also, groups of changes to persistent collections can be done to transient versions, reducing the
amount of objects involved. This is not necessary most of the time, since persistent collections fast
to copy since they share most of their data. Their performance guarantees are not far from their
mutable counterparts.
Due to its simple syntax and high extensibility (via macros, implementation of core interfaces and
reflection), some commonly-seen language features can be added to Clojure with libraries. For
instance, core.typed brings a static type checker, core.async brings simple channel-based
concurrency mechanisms, core.logic brings logic programming.
Designed as a hosted language, it can interoperate with the platform it runs on. While the primary
target is JVM and the entire ecosystem behind Java, alternative implementations can run in other
environments too, such as ClojureCLR running on the Common Language Runtime or
ClojureScript running on JavaScript runtimes (including web browsers). While alternative
implementations may lack some of the functionality from the JVM version, they are still considered
one family of languages.
Versions
https://riptutorial.com/ 2
Version Change log Release Date
1.2.1 2011-03-25
1.2 2010-08-19
1.1 2010-01-04
1.0 2009-05-04
Examples
Installation and Setup
Option 1: Leiningen
Requires JDK 6 or newer.
The easiest way to get started with Clojure is to download and install Leiningen, the de facto
standard tool to manage Clojure projects, then run lein repl to open a REPL.
Linux
OS X
https://riptutorial.com/ 3
Install with MacPorts
lein self-install
Windows
Clojure releases are published as simple JAR files to be run on the JVM. This is what typically
happens inside the Clojure build tools.
You may have to substitute the clojure-1.8.0.jar in that command for the name of the JAR
file that you actually downloaded.
For a better command-line REPL experience (e.g. cycling through your previous
commands), you might want to install rlwrap: rlwrap java -cp clojure-1.8.0.jar clojure.main
Option 3: Boot
Requires JDK 7 or newer.
Boot is a multi-purpose Clojure build tool. Understanding it requires some knowledge of Clojure,
so it may not be the best option for beginners. See the website (click Get Started there) for
installation instructions.
Once it's installed and in your PATH, you can run boot repl anywhere to start a Clojure REPL.
https://riptutorial.com/ 4
The Clojure community puts a large emphasis on interactive development, so quite a lot of
interaction with Clojure happens within a REPL (read-eval-print-loop). When you input an
expression into it, Clojure reads it, evaluates it, and prints the result of the evaluation, all in a
loop.
You should be able to launch a Clojure REPL by now. If you don't know how, follow the
Installation and Setup section in this topic. Once you've got it running, type the following into it:
Then hit Enter. This should print out Hello, world!, followed by this expression's return value, nil.
If you want to run some clojure instantly, try online REPL. For example http://www.tryclj.com/.
After following the instructions above and installing Leiningen, start a new project by running:
This will setup a Clojure project with the default Leiningen template within the <project-name>
folder. There are several templates for Leiningen, which affect the project's structure. Most
commonly is the template "app" used, which adds a main-function and prepares the project to be
packed into a jar-file (which the main-function being the entrypoint of the application). This can be
achieved with this by running:
Assuming you used the app-template to create a new application, you can test that everything was
setup correctly, by entering the created directory and running the application using:
lein run
If you see Hello, World! on your console, you're all set and ready to start building your application.
You can pack this simple application into two jar-files with the following command:
lein uberjar
Note: you need to install Boot before trying this example out. See the Installation and Setup
section if you haven't installed it yet.
Boot allows making executable Clojure files using shebang (#!) line. Place the following text into a
file of your choice (this example assumes it's in the "current working directory" and is named
hello.clj).
https://riptutorial.com/ 5
#!/usr/bin/env boot
This command will tell boot to grab the task boot-new from https://github.com/seancorfield/boot-new
and execute the task with the app template (see link for other templates). The task will create a
new directory called <appname> with a typical Clojure application structure. See the generated
README for more information.
To run the application: boot run. Other commands are specified in build.boot and described in the
README.
https://riptutorial.com/ 6
Chapter 2: Atom
Introduction
An atom in Clojure is a variable that can be changed throughout your program (namespace).
Because most data types in Clojure are immutable (or unchangeable) - you can't change a
number's value without redefining it - atoms are essential in Clojure programming.
Examples
Define an atom
To define an atom, use an ordinary def, but add an atom function before it, like so:
To read an atom's value, simply put the name of the atom, with a @ before it:
@counter ; => 0
A bigger example:
There are two commands to change an atom, swap! and reset!. swap! is given commands, and
changes the atom based on its current state. reset! changes the atom's value completely,
regardless of what the original atom's value was:
https://riptutorial.com/ 7
(while (< @atom 10)
(swap! atom inc)
(println (Math/pow 2 @atom)))
https://riptutorial.com/ 8
Chapter 3: clj-time
Introduction
This documents deals with how to manipulate Date and Time in clojure.
To use this in your application go to your project.clj file and include [clj-time "<version_number>"]
in your :dependencies section.
Examples
Creating a Joda Time
Getting Day Month Year Hour Minute Second from your date-time
https://riptutorial.com/ 9
Checking whether a time is within a time interval
This function tells whether a given time lies within a a given time interval.
The interval function is used is exclusive, which means that is does not include the second
argument of the function within the interval. As an example:
The clj-time.coerce library can help converting other date-time formats to joda time format (clj-
time.core/date-time). The other formats include Java long format, String, Date, SQL Date.
To convert time from other time formats, include the library and use the from- function, e.g.
cljs-time gives us option to add/subtract date-times to other date-times. The date times added
subtracted should be in form of days, months, years, hours etc.
;; Addition
(t/plus example-date (t/months 1)) ;; #<DateTime 2016-02-01T00:00:00.000Z>
(t/plus example-date (t/years 1)) ;; #<DateTime 2017-01-01T00:00:00.000Z>
;; Subtraction
(t/minus example-date (t/days 1)) ;; #<DateTime 2015-12-31T00:00:00.000Z>
https://riptutorial.com/ 10
(t/minus example-date (t/hours 12)) ;; #<DateTime 2015-12-31T12:00:00.000Z>
https://riptutorial.com/ 11
Chapter 4: Clojure destructuring
Examples
Destructuring a vector
Then, for example within a let block, you can extract values from the vector very succinctly as
follows:
Destructuring a map
Then, for example, within a let block you can extract values from the map very succinctly as
follows:
Notice that the values being extracted in each mapping are on the left and the keys they are
associated with are on the right.
If you want to destructure values to bindings with the same names as the keys you can use this
shortcut:
If your keys are strings you can use almost the same structure:
https://riptutorial.com/ 12
And similarly for symbols:
If you want to destructure a nested map, you can nest binding-forms explained above:
(def data
{:foo {:a 1
:b 2}
:bar {:a 10
:b 20}})
And you want to extract the first 3 elements and get the remaining elements as a sequence. This
can be done as follows:
Sometimes you want to destructure key under a map which might not be present in the map, but
you want a default value for the destructured value. You can do that this way:
https://riptutorial.com/ 13
:or {a 1
c 2}} my-map]
(println a b c d))
;= 3 4 2 nil
Destructuring params of a fn
(my-func [1 2 3]) ;= 5
(my-func (range 5)) ;= 3
Destructuring also works for the & rest construct in the param list:
(my-func2 1 2 3) ;= 5
(apply my-func2 (range 5)) ;= 3
(my-func 1 2) ;= 1 2 3 4
(my-func 3 4 :c 5 :d 6) ;= 3 4 5 6
Overview
Destructuring allows you to extract data from various objects into distinct variables. In each
example below, each variable is assigned to its own string (a="a", b="b", &c.)
https://riptutorial.com/ 14
Type Example Value of data / comment
nested vec (let [[[a b] [c d]] data ...) [["a" "b"] ["c" "d"]]
map (let [{a :a b :b c :c} data ...) {:a "a" :b "b" :c "c"}
— alternative: (let [{:keys [a b c]} data ...) When variables are named after the keys.
Tips:
• Default values can be provided using :or, otherwise the default is nil
• Use & rest to store a seq of any extra values in rest, otherwise the extra values are ignored
• A common and useful use of destructuring is for function parameters
• You can assign unwanted parts to a throw-away variable (conventionally: _)
Sometimes when destructuring maps, you would like to bind the destructured values to their
respective key name. Depending on the granularity of the data structure, using the standard
destructuring scheme may be a little bit verbose.
here, the data structure is quite simple with only 3 slots (firstname, lastname, country) but imagine
how cumbersome it would be if we had to repeat all the key names twice for more granular data
structure (having way more slots than just 3).
Instead, a better way of handling this is by using :keys (since our keys are keywords here) and
selecting the key name we would like to bind to like so :
The same intuitive logic applies for other key types like symbols (using :syms ) and plain old strings
(using :strs)
https://riptutorial.com/ 15
;; destructuring string-keyed map
(let [{:strs [lastname firstname country]} john]
(str firstname " " lastname ", " country))
;;"John McCarthy, USA"
(defn print-some-items
[[a b :as xs]]
(println a)
(println b)
(println xs))
(print-some-items [2 3])
2
3
[2 3]
The argument is destructured and the items 2 and 3 are assigned to the symbols a and b. The
original argument, the entire vector [2 3], is also assigned to the symbol xs.
https://riptutorial.com/ 16
Chapter 5: clojure.core
Introduction
This document gives various basic functionalities offered by clojure. There is no explicit
dependency needed for this and comes as a part of org.clojure.
Examples
Defining functions in clojure
(defn x [a b]
(* a b)) ;; public function
=> (x 3 2) ;; 6
=> (x 0 9) ;; 0
(defn- y [a b]
(+ a b)) ;; private function
=> (x (y 1 2) (y 2 3)) ;; 15
When applied on a map, returns a new map with new or updated key val pairs.
It can also be used on a vector for replacing value at the specified index.
(assoc [3 5 6 7] 2 10) ;; [3 5 10 7]
(assoc [1 2 3 4] 6 6) ;; java.lang.IndexOutOfBoundsException
Comparisons are functions in clojure. What that means in (2>1) is (> 2 1) in clojure. Here are all
the comparison operators in clojure.
1. Greater Than
https://riptutorial.com/ 17
(> 2 1) ;; true
(> 1 2) ;; false
2. Less Than
(< 2 1) ;; false
(>= 2 1) ;; true
(>= 2 2) ;; true
(>= 1 2) ;; false
(<= 2 1) ;; false
(<= 2 2) ;; true
(<= 1 2) ;; true
5. Equal To
(= 2 2) ;; true
(= 2 10) ;; false
6. Not Equal To
(not= 2 2) ;; false
(not= 2 10) ;; true
This returns a map without the key-value pairs for the keys mentioned in the function argument. It
can be used to remove information from existing map.
https://riptutorial.com/ 18
Chapter 6: clojure.spec
Syntax
• :: is a shorthand a namespace-qualified keyword. E.g. if we are in the namespace user: ::foo
is a shorthand for :user/foo
• #: or # - map-literal syntax for qualifying keys in a map by a namespace
Remarks
Clojure spec is a new specification/contracts library for clojure available as of version 1.9.
Specs are leveraged in a number of ways including being included in documentation, data
validation, generating data for testing and more.
Examples
Using a predicate as a spec
(clojure.spec/valid? odd? 1)
;;=> true
(clojure.spec/valid? odd? 2)
;;=> false
the valid? function will take a spec and a value and return true if the value conforms to the spec
and false otherwise.
We can write a spec for this function by defining a function spec of the same name:
(clojure.spec/fdef nat-num-count
:args (s/cat :nums (s/coll-of number?))
:ret integer?
https://riptutorial.com/ 19
:fn #(<= (:ret %) (-> % :args :nums count)))
:args takes a regex spec which describes the sequence of arguments by a keyword label
corresponding to the argument name and a corresponding spec. The reason the spec required by
:args is a regex spec is to support multiple arities for a function. :ret specifies a spec for the return
value of the function.
:fn is a spec which constrains the relationship between the :args and the :ret. It is used as a
property when run through test.check. It is called with a single argument: a map with two keys:
:args (the conformed arguments to the function) and :ret (the function's conformed return value).
Registering a spec
In addition to predicates functioning as specs, you can register a spec globally using
clojure.spec/def. def requires that a spec being registered is named by a namespace-qualified
keyword:
(clojure.spec/valid? ::odd-nums 1)
;;=> true
(clojure.spec/valid? ::odd-nums 2)
;;=> false
The ::odd-nums syntax is a shorthand for :user/odd-nums, assuming we are in the user namespace.
:: will qualify the symbol it precedes with the current namesapce.
Rather than pass in the predicate, we can pass in the spec name to valid?, and it will work the
same way.
clojure.spec/and & clojure.spec/or can be used to create more complex specs, using multiple
specs or predicates:
(clojure.spec/valid? ::pos-odd 1)
;;=> true
or works similarly, with one significant difference. When defining an or spec, you must tag each
possible branch with a keyword. This is used in order to provide specific branches which fail in
error messages:
https://riptutorial.com/ 20
(clojure.spec/def ::big-or-small (clojure.spec/or :small #(< % 10) :big #(> % 100)))
(clojure.spec/valid? ::big-or-small 1)
;;=> true
When conforming a spec using or, the applicable spec will be returned which made the value
conform:
(clojure.spec/conform ::big-or-small 5)
;; => [:small 5]
Record specs
At some point in the future, a reader syntax or built-in support for qualifying record keys by the
records' namespace may be introduced. This support already exists for maps.
Map specs
You can spec a map by specifying which keys should be present in the map:
:req is a vector of keys required to be present in the map. You can specify additional options such
as :opt, a vector of keys which are optional.
https://riptutorial.com/ 21
The examples so far require that the keys in the name are namespace-qualified. But it's common
for map keys to be unqualified. For this case, clojure.spec provides :req and :opt equivalents for
unqualified keys: :req-un and :opt-un. Here's the same example, with unqualified keys:
Notice how the specs provided in the :req-un vector as still qualified. clojure.spec, will
automatically confirm the unqualified versions in the map when conforming the values.
namespace map literal syntax allows you to qualify all the keys of a map by a single namespace
succinctly. For example:
Notice the special #: reader syntax. We follow this with the namespace we wish to qualify all the
map keys by. These will then be checked against the specs corresponding to the provided
namespace.
Collections
You can spec collections in a number of ways. coll-of allows you to spec collections and provide
some additional constraints. Here's a simple example:
Constraint options follow the main spec/predicate for the collection. You can constrain the
collection type with :kind like this:
https://riptutorial.com/ 22
The above is false because the collection passed in is not a vector.
The above is false because not all elements in the set are ints.
You can also constrain the size of the collection in a few ways:
You can also enforce uniqueness of the elements in the collection with :distinct:
coll-of ensures all elements in a sequence are checked. For large collections, this can be very
inefficient. every behaves just like coll-of, except it only samples a relatively small number of the
sequences' elements from for conformance. This works well for large collections. Here's an
example:
map-of is similar to coll-of, but for maps. Since maps have both keys and values, you must supply
both a spec for the key and a spec for the value:
Like coll-of, map-of checks conformance of all map key/values. For large maps this will be
inefficient. Like coll-of, map-of supplies every-kv for efficiently sampling a relatively small number
of values from a large map:
https://riptutorial.com/ 23
(clojure.spec/valid? (clojure.spec/every-kv keyword? string?) {:red "red" :green "green"})
;; => true
Sequences
spec can describe and be used with arbitrary sequences. It supports this via a number of regex
spec operations.
catrequires labels for each spec used to describe the sequence. cat describes a sequence of
elements and a spec for each one.
altis used to choose among a number of possible specs for a given element in a sequence. For
example:
Regex sequences can be composed in some very interesting and powerful ways to create
arbitrarily complex sequence-describing specs. Here's a slightly more complex example:
Here ::complex-seq will validate a sequence of one or more pairs of elements, the first being an int
and the second being a map of keyword to int.
https://riptutorial.com/ 24
Chapter 7: clojure.test
Examples
is
The is macro is the core of the clojure.test library. It returns the value of its body expression,
printing an error message if the expression returns a falsey value.
You can group related assertions in deftest unit tests within a context using the testing macro:
(deftest add-nums
(testing "Positive cases"
(is (= 2 (+ 1 1)))
(is (= 4 (+ 2 2))))
(testing "Negative cases"
(is (= -1 (+ 2 -3)))
(is (= -4 (+ 8 -12)))))
This will help clarify test output when run. Note that testing must occur inside a deftest.
deftest is a macro for defining a unit test, similar to unit tests in other languages.
(deftest add-nums
(is (= 2 (+ 1 1)))
(is (= 3 (+ 1 2))))
Here we are defining a test called add-nums, which tests the + function. The test has two assertions.
https://riptutorial.com/ 25
You can then run the test like this in your current namespace:
(run-tests)
Or you can just run the tests for the namespace the test is in:
(run-tests 'your-ns)
are
The are macro is also part of the clojure.test library. It allows you to make multiple assertions
against a template.
For example:
(are [x y] (= x y)
4 (+ 2 2)
8 (* 2 4))
=> true
Here, (= x y) acts as a template which takes each argument and creates an is assertion out of it.
(do
(is (= 4 (+ 2 2)))
(is (= 8 (* 2 4))))
use-fixturesallows to wrap each deftest in namespace with code that runs before and after test. It
can be used for fixtures or stubbing.
Fixtures are just functions that take test function and run it with other necessary steps
(before/after, wrap).
(ns myapp.test
(require [clojure.test :refer :all])
When used with :once, it wraps whole run of tests in current namespace with function
https://riptutorial.com/ 26
(defn database-for-tests [all-tests]
(setup-database)
(all-tests)
(drop-database))
If you are using Leiningen and your tests are located in the test directory in your project root then
you can run your tests using lein test
https://riptutorial.com/ 27
Chapter 8: Collections and Sequences
Syntax
• '() → ()
• '(1 2 3 4 5) → (1 2 3 4 5)
• '(1 foo 2 bar 3) → (1 'foo 2 'bar 3)
• (list 1 2 3 4 5) → (1 2 3 4 5)
• (list* [1 2 3 4 5]) → (1 2 3 4 5)
• [] → []
• [1 2 3 4 5] → [1 2 3 4 5]
• (vector 1 2 3 4 5) → [1 2 3 4 5]
• (vec '(1 2 3 4 5)) → [1 2 3 4 5]
• {} => {}
• {:keyA 1 :keyB 2} → {:keyA 1 :keyB 2}
• {:keyA 1, :keyB 2} → {:keyA 1 :keyB 2}
• (hash-map :keyA 1 :keyB 2) → {:keyA 1 :keyB 2}
• (sorted-map 5 "five" 1 "one") → {1 "one" 5 "five"} (entries are sorted by key when used as
a sequence)
• #{} → #{}
• #{1 2 3 4 5} → #{4 3 2 5 1} (unordered)
• (hash-set 1 2 3 4 5) → #{2 5 4 1 3} (unordered)
• (sorted-set 2 5 4 3 1) → #{1 2 3 4 5}
Examples
Collections
All built-in Clojure collections are immutable and heterogeneous, have literal syntax, and support
the conj, count, and seq functions.
• conjreturns a new collection that is equivalent to an existing collection with an item "added",
in either "constant" or logarithmic time. What exactly this means depends on the collection.
• count returns the number of items in a collection, in constant time.
• seq returns nil for an empty collection, or a sequence of items for a non-empty collection, in
constant time.
Lists
()
;;=> ()
https://riptutorial.com/ 28
A Clojure list is a singly linked list. conj "conjoins" a new element to the collection in the most
efficient location. For lists, this is at the beginning:
(conj () :foo)
;;=> (:foo)
Unlike other collections, non-empty lists are evaluated as calls to special forms, macros, or
functions when evaluated. Therefore, while (:foo) is the literal representation of the list containing
:foo as its only item, evaluating (:foo) in a REPL will cause an IllegalArgumentException to be
thrown because a keyword cannot be invoked as a nullary function.
(:foo)
;; java.lang.IllegalArgumentException: Wrong number of args passed to keyword: :foo
To prevent Clojure from evaluating a non-empty list, you can quote it:
'(:foo)
;;=> (:foo)
'(:foo :bar)
;;=> (:foo :bar)
(+ 1 1)
;;=> 2
'(1 (+ 1 1) 3)
;;=> (1 (+ 1 1) 3)
For this reason, you'll usually want to use list, a variadic function that evaluates all of its
arguments and uses those results to construct a list:
(list)
;;=> ()
(list :foo)
;;=> (:foo)
(list 1 (+ 1 1) 3)
;;=> (1 2 3)
(count ())
;;=> 0
https://riptutorial.com/ 29
(count (conj () :foo))
;;=> 1
You can test whether something is a list using the list? predicate:
(list? ())
;;=> true
(list? nil)
;;=> false
(list? 42)
;;=> false
(list? :foo)
;;=> false
(peek ())
;;=> nil
(peek '(:foo))
;;=> :foo
You can get a new list without the first element using pop:
(pop '(:foo))
;;=> ()
Note that if you try to pop an empty list, you'll get an IllegalStateException:
(pop ())
;; java.lang.IllegalStateException: Can't pop empty list
Finally, all lists are sequences, so you can do everything with a list that you can do with any other
sequence. Indeed, with the exception of the empty list, calling seq on a list returns the exact same
object:
(seq ())
;;=> nil
https://riptutorial.com/ 30
(seq '(:foo))
;;=> (:foo)
Sequences
A sequence is very much like a list: it is an immutable object that can give you its first element or
the rest of its elements in constant time. You can also construct a new sequence from an existing
sequence and an item to stick at the beginning.
You can test whether something is a sequence using the seq? predicate:
(seq? nil)
;;=> false
(seq? 42)
;;=> false
(seq? :foo)
;;=> false
(seq? ())
;;=> true
Anything you get by calling seq or rseq or keys or vals on a non-empty collection is also a
sequence:
https://riptutorial.com/ 31
;;=> true
Remember that all lists are sequences, but not all sequences are lists. While lists support peek and
pop and count in constant time, in general, a sequence does not need to support any of those
functions. If you try to call peek or pop on a sequence that doesn't also support Clojure's stack
interface, you'll get a ClassCastException:
If you call count on a sequence that doesn't implement count in constant time, you won't get an
error; instead, Clojure will traverse the entire sequence until it reaches the end, then return the
number of elements that it traversed. This means that, for general sequences, count is linear, not
https://riptutorial.com/ 32
constant, time. You can test whether something supports constant-time count using the counted?
predicate:
As mentioned above, you can use first to get the first element of a sequence. Note that first will
call seq on their argument, so it can be used on anything "seqable", not just actual sequences:
(first nil)
;;=> nil
(first '(:foo))
;;=> :foo
(first [:foo])
;;=> :foo
(first #{:foo})
;;=> :foo
Also as mentioned above, you can use rest to get a sequence containing all but the first element
of an existing sequence. Like first, it calls seq on its argument. However, it does not call seq on its
result! This means that, if you call rest on a sequence that contains fewer than two items, you'll
get back () instead of nil:
https://riptutorial.com/ 33
(rest nil)
;;=> ()
(rest '(:foo))
;;=> ()
(rest [:foo])
;;=> ()
(rest #{:foo})
;;=> ()
If you want to get back nil when there aren't any more elements in a sequence, you can use next
instead of rest:
(next nil)
;;=> nil
(next '(:foo))
;;=> nil
(next [:foo])
;;=> nil
You can use the cons function to create a new sequence that will return its first argument for first
and its second argument for rest:
Clojure provides a large sequence library with many functions for dealing with sequences. The
important thing about this library is that it works with anything "seqable", not just lists. That's why
the concept of a sequence is so useful; it means that a single function, like reduce, works perfectly
on any collection:
(reduce + [1 2 3])
;;=> 6
https://riptutorial.com/ 34
The other reason that sequences are useful is that, since they don't mandate any particular
implementation of first and rest, they allow for lazy sequences whose elements are only realized
when necessary.
Given an expression that would create a sequence, you can wrap that expression in the lazy-seq
macro to get an object that acts like a sequence, but will only actually evaluate that expression
when it is asked to do so by the seq function, at which point it will cache the result of the
expression and forward first and rest calls to the cached result.
For finite sequences, a lazy sequence usually acts the same as an equivalent eager sequence:
(defn eager-fibonacci [a b]
(cons a (eager-fibonacci b (+' a b))))
(defn lazy-fibonacci [a b]
(lazy-seq (cons a (lazy-fibonacci b (+' a b)))))
Vectors
[]
;;=> []
[:foo]
;;=> [:foo]
[:foo :bar]
;;=> [:foo :bar]
[1 (+ 1 1) 3]
;;=> [1 2 3]
In addition using to the literal syntax, you can also use the vector function to construct a vector:
(vector)
;;=> []
(vector :foo)
https://riptutorial.com/ 35
;;=> [:foo]
(vector 1 (+ 1 1) 3)
;;=> [1 2 3]
You can test whether something is a vector using the vector? predicate:
(vector? [])
;;=> true
(vector? nil)
;;=> false
(vector? 42)
;;=> false
(vector? :foo)
;;=> false
(conj [] :foo)
;;=> [:foo]
(count [])
;;=> 0
(peek [])
;;=> nil
(peek [:foo])
;;=> :foo
https://riptutorial.com/ 36
;;=> :bar
You can get a new vector without the last element using pop:
(pop [:foo])
;;=> []
Note that if you try to pop an empty vector, you'll get an IllegalStateException:
(pop [])
;; java.lang.IllegalStateException: Can't pop empty vector
Unlike lists, vectors are indexed. You can get an element of a vector by index in "constant" time
using get:
In addition, vectors themselves are functions that take an index and return the element at that
index:
([:foo :bar] 0)
;;=> :foo
([:foo :bar] 1)
;;=> :bar
However, if you call a vector with an invalid index, you'll get an IndexOutOfBoundsException instead
of nil:
([:foo :bar] 2)
;; java.lang.IndexOutOfBoundsException:
You can get a new vector with a different value at a particular index using assoc:
https://riptutorial.com/ 37
(assoc [:foo :bar] 1 42)
;;=> [:foo 42]
If you pass an index equal to the count of the vector, Clojure will add the element as if you had
used conj. However, if you pass an index that is negative or greater than the count, you'll get an
IndexOutOfBoundsException:
(seq [])
;;=> nil
(seq [:foo])
;;=> (:foo)
Since vectors are indexed, you can also get a reversed sequence of a vector's items using rseq:
(rseq [])
;;=> nil
(rseq [:foo])
;;=> (:foo)
Note that, although all lists are sequences, and sequences are displayed in the same way as lists,
not all sequences are lists!
'(:foo :bar)
;;=> (:foo :bar)
https://riptutorial.com/ 38
;;=> false
Sets
Like maps, sets are associative and unordered. Unlike maps, which contain mappings from keys
to values, sets essentially map from keys to themselves.
#{}
;;=> #{}
#{:foo}
;;=> #{:foo}
#{:foo :bar}
;;=> #{:bar :foo}
As with maps, the order in which elements appear in a literal set doesn't matter:
You can test whether something is a set using the set? predicate:
(set? #{})
;;=> true
(set? #{:foo})
;;=> true
(set? nil)
;;=> false
(set? 42)
;;=> false
(set? :foo)
;;=> false
You can test whether a map contains a given item in "constant" time using the contains? predicate:
https://riptutorial.com/ 39
(contains? #{} nil)
;;=> false
In addition, sets themselves are functions that take an element and return that element if it is
present in the set, or nil if it isn't:
(#{} :foo)
;;=> nil
(#{:foo} :foo)
;;=> :foo
(#{:foo} :bar)
;;=> nil
(#{} nil)
;;=> nil
(#{nil} nil)
;;=> nil
You can use conj to get a set that has all the elements of an existing set, plus one additional item:
You can use disj to get a set that has all the elements of an existing set, minus one item:
(count #{})
;;=> 0
https://riptutorial.com/ 40
(count (conj #{} :foo))
;;=> 1
(seq #{})
;;=> nil
(seq #{:foo})
;;=> (:foo)
Maps
Unlike the list, which is a sequential data structure, and the vector, which is both sequential and
associative, the map is exclusively an associative data structure. A map consists of a set of
mappings from keys to values. All keys are unique, so maps support "constant"-time lookup from
keys to values.
{}
;;=> {}
{:foo :bar}
;;=> {:foo :bar}
Each pair of two elements is a key-value pair. So, for instance, the first map above has no
mappings. The second has one mapping, from the key :foo to the value :bar. The third has two
mappings, one from the key :foo to the value :bar, and one from the key :baz to the value :qux.
Maps are inherently unordered, so the order in which the mappings appear doesn't matter:
You can test whether something is a map using the map? predicate:
(map? {})
;;=> true
https://riptutorial.com/ 41
(map? {:foo :bar :baz :qux})
;;=> true
(map? nil)
;;=> false
(map? 42)
;;=> false
(map? :foo)
;;=> false
You can test whether a map contains a given key in "constant" time using the contains? predicate:
You can get the value associated with a key using get:
https://riptutorial.com/ 42
In addition, maps themselves are functions that take a key and return the value associated with
that key:
You can get an entire map entry (key and value together) as a two-element vector using find:
You can extract the key or value from a map entry using key or val, respectively:
Note that, although all Clojure map entries are vectors, not all vectors are map entries. If you try to
call key or val on anything that's not a map entry, you'll get a ClassCastException:
https://riptutorial.com/ 43
(key [:foo :bar])
;; java.lang.ClassCastException:
You can test whether something is a map entry using the map-entry? predicate:
You can use assoc to get a map that has all the same key-value pairs as an existing map, with one
mapping added or changed:
You can use dissoc to get a map that has all the same key-value pairs as an existing map, with
possibly one mapping removed:
https://riptutorial.com/ 44
(count {})
;;=> 0
(seq {})
;;=> nil
Again, maps are unordered, so the ordering of the items in a sequence that you get by calling seq
on a map is undefined.
You can get a sequence of just the keys or just the values in a map using keys or vals,
respectively:
(keys {})
;;=> nil
(vals {})
;;=> nil
Clojure 1.9 adds a literal syntax for more concisely representing a map where the keys share the
same namespace. Note that the map in either case is identical (the map does not "know" the
default namespace), this is merely a syntactic convenience.
https://riptutorial.com/ 45
sequences
https://riptutorial.com/ 46
Chapter 9: core.async
Examples
basic channel operations: creating, putting, taking, closing, and buffers.
core.async is about making processes that take values from and put values into channels.
You can put any value (Strings, numbers, maps, collections, objects, even other channels, etc.)
into a channel, except nil:
;; WON'T WORK
(a/>!! my-channel nil)
=> IllegalArgumentException Can't put nil on channel
Depending on the channel's buffer, >!! may block the current thread.
https://riptutorial.com/ 47
From inside a (go ...) block, you can - and should - use a/>! instead of a/>!!:
The logical behaviour will be the same as a/>!!, but only the logical process of the goroutine will
block instead of the actual OS thread.
;; NEVER DO THIS
(a/go
(a/>!! ch :item))
;; creating a channel
(def ch (a/chan 3))
;; putting some items in it
(do
(a/>!! ch :item-1)
(a/>!! ch :item-2)
(a/>!! ch :item-3))
;; taking a value
(a/<!! ch) ;; => :item-1
(a/<!! ch) ;; => :item-2
If no item is available in the channel, a/<!! will block the current Thread until a value is put in the
channel (or the channel is closed, see later):
(def ch (a/chan))
(a/<!! ch) ;; blocks until another process puts something into ch or closes it
From inside a (go ...) block, you can - and should - use a/<! instead of a/<!!:
The logical behaviour will be the same as a/<!!, but only the logical process of the goroutine will
block instead of the actual OS thread.
;; NEVER DO THIS
(a/go
(a/<!! ch))
Closing channels
https://riptutorial.com/ 48
You close a channel with a/close!:
(a/close! ch)
Once a channel is closed, and the all data in the channel has been exhausted, takes will always
return nil:
;; taking from ch will return the items that were put in it, then nil
(a/<!! ch) ;; => :item-1
(a/<!! ch) ;; => :item-2
(a/<!! ch) ;; => nil
(a/<!! ch) ;; => nil
(a/<!! ch) ;; => nil
;; once the channel is closed, >!! will have no effect on the channel:
(a/>!! ch :item-3)
=> false ;; false means the put did not succeed
(a/<!! ch) ;; => nil
(a/put! ch :item)
(a/put! ch :item (fn once-put [closed?] ...)) ;; callback function, will receive
In ClojureScript, since blocking the current Thread is not possible, a/>!! is not supported, and put!
is the only way to put data into a channel from outside of a (go) block.
https://riptutorial.com/ 49
Dropping buffer example:
https://riptutorial.com/ 50
Chapter 10: Emacs CIDER
Introduction
CIDER is the acronym for Clojure(script) Interactive Development Environment that Rocks. It is an
extension to emacs. CIDER aims to provide an interactive development environment to the
programmer. CIDER is built on top of nREPL, a networked REPL server and SLIME served as the
principle inspiration for CIDER.
Examples
Function Evaluation
CIDER function cider-eval-last-sexp can be used to execute the the code while editing the code
inside the buffer. This function is by default binded to C-x C-e or C-x C-e.
Evaluate the form preceding point and display the result in the echo area and/or in an
buffer overlay.
For example:
(defn say-hello
[username]
(format "Hello, my name is %s" username))
(defn introducing-bob
[]
(say-hello "Bob")) => "Hello, my name is Bob"
Performing C-x C-e or C-c C-e while your cursor is just ahead of the ending paren of say-hello
function call will output the string Hello, my name is Bob.
Pretty Print
CIDER function cider-insert-last-sexp-in-repl can be used to execute the the code while editing
the code inside the buffer and get the output pretty printed in a different buffer. This function is by
default binded to C-c C-p.
Evaluate the form preceding point and pretty-print the result in a popup buffer.
For example
https://riptutorial.com/ 51
(def databases {:database1 {:password "password"
:database "test"
:port "5432"
:host "localhost"
:user "username"}
(defn get-database-config
[]
databases)
(get-database-config)
Performing C-c C-p while your cursor is just ahead of the ending paren of get-database-config
function call will output the pretty printed map in a new popup buffer.
{:database1
{:password "password",
:database "test",
:port "5432",
:host "localhost",
:user "username"},
:database2
{:password "password",
:database "different_test_db",
:port "5432",
:host "localhost",
:user "vader"}}
https://riptutorial.com/ 52
Chapter 11: File Operations
Examples
Overview
(slurp "./small_file.txt")
(use 'clojure.java.io)
(with-open [rdr (reader "./file.txt")]
(line-seq rdr) ; returns lazy-seq
) ; with-open macro calls (.close rdr)
(use 'clojure.java.io)
(with-open [wrtr (writer "./log.txt" :append true)]
(.write wrtr "2016-07-26 New entry.")
) ; with-open macro calls (.close wrtr)
(use 'clojure.java.io)
(with-open [wrtr (writer "./file.txt")]
(.write wrtr "Everything in file.txt has been replaced with this text.")
) ; with-open macro calls (.close wrtr)
Notes:
• You can specify URLs as well as files
• Options to (slurp) and (spit) are passed to clojure.java.io/reader and /writer, respectively.
https://riptutorial.com/ 53
Chapter 12: Functions
Examples
Defining Functions
An optional Docstring that explains and document what the function does.
(defn welcome
"Return a welcome message to the world"
...)
(defn welcome
"Return a welcome message"
[name]
...)
The body, which describes the procedures the function carries out.
(defn welcome
"Return a welcome message"
[name]
(str "Hello, " name "!"))
Calling it:
"Hello, World!"
(defn welcome
"Without parameters"
[]
"Hello!")
https://riptutorial.com/ 54
(defn square
"Take one parameter"
[x]
(* x x))
(defn multiplier
"Two parameters"
[x y]
(* x y))
Arity
The number of arguments a function takes. Functions support arity overloading, which means that
functions in Clojure allow for more than one "set" of arguments.
(defn sum-args
;; 3 arguments
([x y z]
(+ x y z))
;; 2 arguments
([x y]
(+ x y))
;; 1 argument
([x]
(+ x 1)))
The arities don't have to do the same job, each arity can do something unrelated:
(defn do-something
;; 2 arguments
([first second]
(str first " " second))
;; 1 argument
([x]
(* x x x)))
A Clojure function can be defined to take an arbitrary number of arguments, using the symbol & in
its argument list. All remaining arguments are collected as a sequence.
Calling:
https://riptutorial.com/ 55
=> (sum-and-multiply 2 1 2 3) ;; 2*(1+2+3)
12
There are two ways to define an anonymous function: the full syntax and a shorthand.
(fn [x y] (+ x y))
This expression evaluates to a function. Any syntax you can use with a function defined with defn (
&, argument destructuring, etc.), you can also do with with the fn form. defn is actually a macro that
just does (def (fn ...)).
#(+ %1 %2)
This is the shorthand notation. Using the shorthand notation, you don't have to name arguments
explicitly; they'll be assigned the names %1, %2, %3 and so on according to the order they're passed
in. If the function only has one argument, its argument is called just %.
Supported Syntax
You can use varargs with shorthand anonymous functions. This is completely legal:
It takes a variable number of arguments and returns true if every one of them is even:
https://riptutorial.com/ 56
including a name, as in the following example. This is especially useful if the function needs to call
itself but also in stack traces.
https://riptutorial.com/ 57
Chapter 13: Getting started with web
development
Examples
Create new Ring application with http-kit
Ring is de-facto standard API for clojure HTTP applications, similar to Ruby's Rack and Python's
WSGI.
(ns test.core
(:gen-class)
(:require [org.httpkit.server :refer [run-server]]))
Define ring request handler. Request handlers are just functions from request to response and
response is just a map:
Here we just return 200 OK with the same content for any request.
(defn -main
[& args]
(run-server app {:port 8080}))
https://riptutorial.com/ 58
Luminus is a Clojure micro-framework based on a set of lightweight libraries. It aims to provide a
robust, scalable, and easy to use platform. With Luminus you can focus on developing your app
the way you want without any distractions. It also has very good documentation that covers some
of the majour topics
It is very easy to start with luminus. Just create a new project with the following commands:
Running lein new luminus myapp will create an application using the default profile template.
However, if you would like to attach further functionality to your template you can append profile
hints for the extended functionality.
Web Servers
• +aleph - adds Aleph server support to the project
• +jetty - adds Jetty support to the project
• +http-kit - adds the HTTP Kit web server to the project
databases
• +h2 - adds db.core namespace and H2 db dependencies
• +sqlite - adds db.core namespace and SQLite db dependencies
• +postgres - adds db.core namespace and add PostreSQL dependencies
• +mysql - adds db.core namespace and add MySQL dependencies
• +mongodb - adds db.core namespace and MongoDB dependencies
• +datomic - adds db.core namespace and Datomic dependencies
miscellaneous
• +auth - adds Buddy dependency and authentication middleware
• +auth-jwe - adds Buddy dependency with the JWE backend
• +cider - adds support for CIDER using CIDER nREPL plugin
• +cljs - adds [ClojureScript][cljs] support with Reagent
• +re-frame - adds [ClojureScript][cljs] support with re-frame
• +cucumber - a profile for cucumber with clj-webdriver
• +swagger - adds support for Swagger-UI using the compojure-api library
• +sassc - adds support for SASS/SCSS files using SassC command line compiler
• +service - create a service application without the front-end boilerplate such as HTML
templates
• +war - add support of building WAR archives for deployment to servers such as Apache
Tomcat (should NOT be used for Immutant apps running on WildFly)
https://riptutorial.com/ 59
• +site - creates template for site using the specified database (H2 by default) and
ClojureScript
To add a profile simply pass it as an argument after your application name, eg:
You can also mix multiple profiles when creating the application, eg:
https://riptutorial.com/ 60
Chapter 14: Java interop
Syntax
• . let's you access instance methods
• .- let's you access instance fields
• .. macro expanding to multiple nested invocations of .
Remarks
As a hosted language, Clojure provides excellent interoperability support with Java. Clojure code
can also be called directly from Java.
Examples
Calling an instance method on a Java object
(.substring "hello" 0 2)
;;=> "he"
(java.awt.Point. 0 1)
;;=> => #object[java.awt.Point 0x3776d535 "java.awt.Point[x=0,y=1]"]
Or
https://riptutorial.com/ 61
(new java.awt.Point 0 1)
;;=> => #object[java.awt.Point 0x3776d535 "java.awt.Point[x=0,y=1]"]
(System/currentTimeMillis)
;;=> 1469493415265
You can call a Clojure function from Java code by looking up the function and invoking it:
This looks up the * function from the clojure.core namespace and invokes it with the arguments 2
& 2.
https://riptutorial.com/ 62
Chapter 15: Macros
Syntax
• The ' symbol used in the macroexpand example is just syntactic sugar for the quote
operator. You could have written (macroexpand (quote (infix 1 + 2))) instead.
Remarks
Macros are just functions that run at compile time, i.e. during the eval step in a read-eval-print-loop
.
Reader macros are another form of macro that gets expanded at read time, rather than compile
time.
• alpha-renaming, Since macro is expand binding name conflict could arise. Binding conflict is
not very intuitive to solve when using the macro. This is why, whenever a macro adds a
binding to the scope, it is mandatory to use the # at the end of each symbol.
Examples
Simple Infix Macro
Clojure uses prefix notation, that is: The operator comes before its operands.
(+ 1 2)
;; => 3
Macros allow you to manipulate the Clojure language to a certain degree. For example, you could
implement a macro that let you write code in infix notation (e.g., 1 + 2):
https://riptutorial.com/ 63
list with the values of the parameters provided to the infix macro and returns that.
defmacro is a special form because it behaves a little differently compared to other Clojure
constructs: Its parameters are not immediately evaluated (when we call the macro). This is what
allows us to write something like:
(infix 1 + 2)
;; => 3
The infix macro will expand the 1 + 2 arguments into (+ 1 2), which is a valid Clojure form that
can be evaluated.
If you want to see what the infix macro generates, you can use the macroexpand operator:
macroexpand, as implied by its name, will expand the macro (in this case, it will use the infix macro
to transform 1 + 2 into (+ 1 2)) but won't allow the result of the macro expansion to be evaluated
by Clojure's interpreter.
(defmacro and
"Evaluates exprs one at a time, from left to right. If a form
returns logical false (nil or false), and returns that value and
doesn't evaluate any of the other expressions, otherwise it returns
the value of the last expr. (and) returns true."
{:added "1.0"}
([] true)
([x] x)
([x & next]
`(let [and# ~x]
(if and# (and ~@next) and#))))
• called syntax-quote is like (quote), but recursive: it causes (let …), (if …), etc to not
`
evaluate during macro expansion but to output as is
• ~ aka unquote cancels syntax-quote for single form inside syntax-quoted form. So x's value
is outputted when expanding macro (instead of outputting x symbol)
• ~@ aka unquote-splicing is like unquote but takes list argument and expands it, each list item
to separate form
• # appends unique id to symbols to prevent name conflicts. It appends the same id for the
same symbol inside syntax-quoted expression, so and# inside let and and# inside if will get
the same name
https://riptutorial.com/ 64
Chapter 16: Parsing logs with clojure
Examples
Parse a line of log with record & regex
Test it :
(parser sample)
Result :
https://riptutorial.com/ 65
Chapter 17: Pattern Matching with core.match
Remarks
The core.match library implements a pattern match compilation algorithm that uses the notion of
"necessity" from lazy pattern matching.
Examples
Matching Literals
(let [x true
y true
z true]
(match [x y z]
[_ false true] 1
[false true _ ] 2
[_ _ false] 3
[_ _ true] 4))
;=> 4
Matching a Vector
(let [v [1 2 3]]
(match [v]
[[1 1 1]] :a0
[[1 _ 1]] :a1
[[1 2 _]] :a2)) ;; _ is used for wildcard matching
;=> :a2
Matching a Map
;=> :a1
(match [['asymbol]]
[['asymbol]] :success)
;=> :success
https://riptutorial.com/ 66
Read Pattern Matching with core.match online: https://riptutorial.com/clojure/topic/2569/pattern-
matching-with-core-match
https://riptutorial.com/ 67
Chapter 18: Performing Simple Mathematical
Operations
Introduction
This is how you would add some numbers in Clojure syntax. Since the method occurs as the first
argument in the list, we are evaluating the + (or addition) method on the rest of the arguments in
the list.
Remarks
Performing mathematical operations is the basis of manipulating data and working with lists.
Therefore, understand how it works is key to progressing in one's understanding of Clojure.
Examples
Math Examples
;; returns 3
(+ 1 2)
;; returns 300
(+ 50 210 40)
;; returns 2
(/ 8 4)
https://riptutorial.com/ 68
Chapter 19: Setting up your development
environment
Examples
Light Table
Light Table is a good editor to learn, experiment and run Clojure projects.
You can also run lein/boot projects by opening project.clj file. It will load all project dependencies.
It supports inline evalution, plugins and much more, so there's no need to add print statements
and check the output in the console. You can run individual lines or code blocska by pressing ctrl
+ enter. To run partial code, select the code and press ctrl + enter. check the following
screenshot for how you can use Light Table to learn and experiment with Clojure code.
Pre-built binaries of Light Table can be found here. No further setup is required.
Light Table is able to automatically locate your Leiningen project and evaluate your code. If you
don't have Leiningen installed, install it using the instructions here.
Documentation: docs.lighttable.com
https://riptutorial.com/ 69
Emacs
To setup Emacs for working with Clojure, install clojure-mode and cider package from melpa:
Now when you open a .clj file, run M-x cider-jack-in to connect to a REPL. Alternatively, you can
use C-u M-x (cider-jack-in) to specify the name of a lein or boot project, without having to visit any
file in it. You should now be able to evaluate expressions in your file using C-x C-e.
Editing code in lisp-like languages is much more comfortable with a paren-aware editing plugin.
Emacs has several good options.
• pareditA classic Lisp editing mode that has a steeper learning curve, but provides a lot of
power once mastered.
• smartparensA newer project with similar goals and usage to paredit, but also provides
reduced capabilities with non-Lisp languages.
• parinfer A much simpler Lisp editing mode that operates mainly via inferring proper paren
nesting from indentation.
Installation is more involved, see the Github page for parinfer-mode for setup instructions.
Atom
https://riptutorial.com/ 70
Download and install the latest IDEA version.
After restarting IDEA, Cursive should be working out of the box. Follow the user guide to fine-tune
appearance, keybindings, code style etc.
Note: Like IntelliJ, Cursive is a commercial product, with a 30-day evaluation period. Unlike
IntelliJ, it doesn't have a community edition. Free non-commercial licences are available to
individuals for non-commercial use, including personal hacking, open-source and student work.
The licence is valid for 6 months and can be renewed.
Spacemacs + CIDER
Spacemacs is a distribution of emacs that comes with a lot of packages preconfigured and easily
installed. Also, it is very friendly for those who are familiar with vim style of editing. Spacemacs
provides a CIDER-based Clojure layer.
To install and configure it for use with Clojure, first install emacs. Then make a backup of your
previous configurations:
$ mv ~/.emacs.d ~/.emacs.d.backup
Now, open emacs. It will ask you some questions regarding your preferences. Then it downloads
more packages and configures your emacs. After that the spacemacs is installed, you are ready to
add Clojure support. Press SPC f e d to open your .spacemacs file for configuration. Find
dotspacemacs-configuration-layers in the file, under it there is an open paren. Anywhere in between
the parens in a new line type clojure.
(defun dotspacemacs/layers ()
(setq-default
;; ...
dotspacemacs-configuration-layers
'(clojure
;; ...
)
;; ...
))
Press SPC f e R to save and install the clojure layer. Now, in any .clj file if you press , s i
spacemacs will try to spawn a new clojure REPL connection to your project, and if it succeeds it
will show in the statusbar, which afterwards you can press , s s to open a new REPL buffer to
evaluate your codes.
For more information about spacemacs and cider contact their documentations. Spacemacs docs,
Cider docs
https://riptutorial.com/ 71
Vim
and also relate to syntax highlighting, omni completion, advanced highlighting and so on:
1. vim-clojure-static (if you have a vim older than 7.3.803, newer versions ship with this)
2. vim-clojure-highlight
https://riptutorial.com/ 72
Chapter 20: Threading Macros
Introduction
Also known as arrow macros, threading macros convert nested function calls into a linear flow of
function calls.
Examples
Thread Last (->>)
This macro gives the output of a given line as the last argument of the next line function call. For
e.g.
is same as
(->> 2
(+ 3)
(str)
(prn))
This macro gives the output of a given line as the first argument of the next line function call. For
e.g.
(-> {:a 1}
(assoc :b 1) ;;(assoc map key val)
(rename-keys {:b :new-b})) ;;(rename-keys map key-newkey-map)
Thread as (as->)
This is a more flexible alternative to thread first or thread last. It can be inserted anywhere in the
list of parameters of the function.
(as-> [1 2] x
(map #(+ 1 %) x)
(if (> (count x) 2) "Large" "Small"))
https://riptutorial.com/ 73
Read Threading Macros online: https://riptutorial.com/clojure/topic/9582/threading-macros
https://riptutorial.com/ 74
Chapter 21: Transducers
Introduction
Transducers are composable components for processing data independently of the context. So
they can be used to process collections, streams, channels, etc. without knowledge of their input
sources or output sinks.
The Clojure core library was extended in 1.7 so that the sequence functions like map, filter, take,
etc. return a transducer when called without a sequence. Because transducers are functions with
specific contracts, they can be composed using the normal comp function.
Remarks
Transducers allow the lazyness to be controlled as they are consumed. For example into is eager
as would be expected, but sequence will lazily consume the sequence through the transducer.
However, the lazyness guarantee is different. Enough of the source will be consumed to produce
an element initially:
(take 0 (sequence (comp (map #(do (prn '-> %) %)) (remove number?)) (range 5)))
;; -> 0
;; -> 1
;; -> 2
;; -> 3
;; -> 4
;; => ()
Examples
Small transducer applied to a vector
https://riptutorial.com/ 75
This example creates a transducer assigned to the local xf and uses transduce to apply it to some
data. The transducer add's one to each of it's inputs and only returns the even numbers.
transduce is like reduce, and collapses the input collection to a single value using the provided +
function.
This reads like the thread-last macro, but separates the input data from the computations.
(->> [1 2 3 4 5 6 7 8 9 10]
(map inc)
(filter even?)
(reduce +))
;; => 30
Applying transducers
Creating/Using Transducers
So the most used functions on Clojure map and filter have been modified to return transducers
(composable algorithmic transformations), if not called with a collection. That means:
The advantage: the functions can be composed into a single function by comp , which means
traversing the collection just once. Saves run time by over 50% in some scenarios.
https://riptutorial.com/ 76
Definition:
Usage:
;; We do this:
(into [] composed-fn [1 8 3 10 5])
;; Output: [9 11]
https://riptutorial.com/ 77
Chapter 22: Truthiness
Examples
Truthiness
Examples:
Booleans
Any value in Clojure is considered truthy unless it is false or nil. You can find the truthiness of a
value with (boolean value). You can find the truthiness of a list of values using (or), which returns
true if any arguments are truthy, or (and) which returns true if all arguments are truthy.
https://riptutorial.com/ 78
Chapter 23: Vars
Syntax
• (def symbol value)
• (def symbol "docstring" value)
• (declare symbol_0 symbol_1 symbol_2 ...)
Remarks
This should not be confused with (defn), which is used for defining functions.
Examples
Types of Variables
• numbers
Types of numbers:
○ integers
○ longs (numbers larger than 2^31 - 1)
○ floats (decimals)
• strings
• collections
Types of collections:
○ maps
○ sequences
○ vectors
• functions
https://riptutorial.com/ 79
Credits
S.
Chapters Contributors
No
Collections and
8 Alex Miller, Kenogu Labz, nXqd, Sam Estep
Sequences
Pattern Matching
17 Kiran
with core.match
https://riptutorial.com/ 80
Mathematical
Operations
https://riptutorial.com/ 81