Clojure Guides_ Language_ clojure.core

Download as pdf or txt
Download as pdf or txt
You are on page 1of 34

Language: clojure.

core
This guide covers:

Key functions of clojure.core


Key macros of clojure.core
Key vars of clojure.core
Essential special forms

This guide is by no means comprehensive and does not try to explain each function/macro/form in
depth. It is an overview, the goal is to briefly explain the purpose of each item and provide links to other
articles with more information.

This work is licensed under a Creative Commons Attribution 3.0 Unported License
(https://creativecommons.org/licenses/by/3.0/) (including images & stylesheets). The source is available
on Github (https://github.com/clojure-doc/clojure-doc.github.io).

What Version of Clojure Does This Guide Cover?


This guide covers Clojure 1.11.

Binding
let
(let [bindings*] exprs*)

let takes a vector of symbol/expression pairs (bindings) followed by a variable number of expressions.

let allows binding of locals (roughly equivalent to variables in many other languages), and evaluates the
expressions (with those bindings in scope).

The body of a let statement also provides an implicit do that allows for multiple statements in the body
of let .

A basic example:

(let [x 1 y 2]
(println x y))

1 2
nil

let does its bindings sequentially, meaning it's possible to reference previous bindings:
(let [a 5
b (* a 2)
c (+ a b)]
(println "c is" c))

nil

let can also be nested, and the scope is lexically determined. This means that a binding's value is
determined by the nearest binding form for that symbol.

This example demonstrates the lexical scoping of the let form.

(let [x 1]
(println x) ; prints 1
(let [x 2]
(println x)) ; prints 2
(println x)) ; outside the nested let, prints 1 again

1
2
1
nil

let bindings are immutable and can be destructured.

See: Sections about destructuring in Introduction (/articles/tutorials/introduction/#destructuring) and


Functions (/articles/language/functions/#destructuring-of-function-arguments) pages.

def
(def symbol doc-string? init?)

def takes a symbol, an optional docstring, and an optional init value (although it is very rare that you
would omit the init value), and creates (or re-assigns) a var in the current namespace with the name of the
symbol. If an init value is supplied, the root binding of the var is assigned to that value. Redefining a var
with an init value will re-assign the root binding. If no init value is supplied and the var is newly-created, it
will be 'unbound', otherwise the var already exists and its value is unchanged.

A root binding is a value that is shared across all threads.

(def x)
x ; x is an 'unbound' var, or nil in clojurescript
; => #object [clojure.lang.Var$Unbound 0x1de19fc6 "Unbound: #'user/x"]
(def x 7)
x ; x is now 7
; => 7
(def x)
x ; x is still 7, deffing with no value doesn't unbind an existing value
; => 7
def vs let
Superficially, def and let both give names to values. A key difference is that let bindings are scoped
and don't have a namespace, while vars created with def are 'global' and qualified to a namespace. A
name/binding that should only exist within (for example) a function should be created with let , and it's
very rarely needed/advisable to use def within a function or other form.

; def creates (and returns) vars in the current namespace


(def my-secret-number 5)
(def my-secret-string "hi")
(let [my-secret-number 7] ; this is a local that's not available outside the let
(vector my-secret-number cljs.user/my-secret-number my-secret-string))

[7 5 "hi"]

In the output of this example:

my-secret-number resolves to the local from the surrounding let


cljs.user/my-secret-number resolves to the var created by def (because the let binding
doesn't have a namespace)
my-secret-string resolves to the var - since there's no local named my-secret-string , clojure
looks for bindings available in the current namespace.

See Vars and the Global Environment (https://clojure.org/reference/vars) in the official Clojure reference
documentation for more details, which also covers how to attach metadata to such Vars.

declare
(declare names*)

declare takes zero or more symbols and behaves as if you had used def on each without an init value.

declare provides a simple way of creating 'forward declarations'. This allows for referencing of a var
before it has been supplied a value.

There are much better methods of value-based dispatch or code architecture in general, but this presents
a simple situation forward declarations would be necessary.
(declare func<10 func<20)

;; without declare you will receive an error similar to:
;; "Unable to resolve symbol: func10 in this context"

(defn func<10 [x]
(cond
(< x 10) (func<10 (inc x))
(< x 20) (func<20 x)
:else "too far!"))

(defn func<20 [x]
(cond
(< x 10) (func<10 x)
(< x 20) "More than 10, less than 20"
:else "too far!"))

#'cljs.user/func<20

No matter which order you put func<10 and func<20 in, there will be a reference to a var that does not yet
exist when the compiler does the initial evaluation of top-level forms.

declare defines the var with no binding so that the the var exists when it is referenced later in the code.

defn
(defn name doc-string? attr-map? [params*] prepost-map? body)
(defn name doc-string? attr-map? ([params*] prepost-map? body)+ attr-map?)

defn takes a symbol, an optional doc string, an optional meta-data map, a vector of arguments and a
variable number of expressions.

defn is the primary way of defining functions. It allows for convenient definition of metadata about its
argslist and documentation (docstrings). defn inherently allows for quick documentation of functions that
can be retrieved with doc . This feature should be used almost universally.

(defn func [x]


x)
(func 7)

Because defn has multiple forms and a handful of optional parameters, there's a separate section that
does a deep dive on defining functions (/articles/language/functions).

See the def Special Form (https://clojure.org/reference/special_forms#def) for more detail about how
defn provides additional metadata and convenience over def .
Branching/Grouping
do
(do exprs*)

do is used to 'group' expressions together. It executes the expressions in order and returns the return
value of the final expression. It is often used when it's necessary to treat multiple expressions as one
'block', like an argument to if .

if
(if test then else?)

if takes two or three expressions -- a condition expression, a 'then' expression, and optionally an 'else'
expression. If the 'else' expression is not supplied, it defaults to nil .

if is the primary method of conditional execution, and other conditionals are built upon if .

The condition is evaluated, and if its value is truthy -- anything except nil or false -- the 'then'
expression is evaluated and the result returned (the 'else' expression is not evaluated).

If the condition returns nil or false the 'else' expression is evaluated and returned (the 'then'
expression is not evaluated).

(if 0 "second") ; 0 is a 'true' value. Only false or nil are 'false'

"second"

(if nil "second" "third")

"third"

(if (< 10 9) "second" "third") ; (< 10 9) returns false

"third"

; seq returns nil for an empty sequence,


; so the third expression (defaulted to nil) is returned
(if (seq '()) "second")

nil
(if (nil? (= 1 2)) "second" "third") ; differentiate between nil and false if nee

"third"

; to do multiple things based on the condition, use a `do`


(if (> 4 3)
(do
(println "4 is greater than 3...")
(println "so 3 is less than 4")
"4!")
(println "Uh oh, math is broken."))

4 is greater than 3...


so 3 is less than 4
"4!"

when
(when test body*)

when takes a test and zero or more body expressions. If the test returns a truthy value, all the body
expressions are evaluated in an implicit do , and the last return value is the return value of when . If the
test is not truthy, nil is returned (the body expressions are not evaluated at all).

Put another way, (when test body) is transformed to (if test (do body)) .

;; (= 1 2) is false so the other expressions are not evaluated


(when (= 1 2) (println "hey") 10)

nil

;; (< 10 11) is true so both expressions are evaluated and the last value returne
(when (< 10 11) (println "hey") 10)

hey
10

There might be some unfamiliar syntax, but this demo shows that the when is transformed to an if
expression (this is an example of a macro (/articles/language/macros)).

(macroexpand '(when (< 3 4) (println "true text") (println "more true text")))

(if (< 3 4) (do (println "true text") (println "more true text")))

Looping
recur
(recur exprs*)

recur allows for self-recursion without consuming stack space proportional to the number of recursive
calls made. Due to the lack of tail-call optimization on the JVM currently, this is the only method of
recursion that does not consume excess stack space.

recur takes a number of arguments identical to the point of recursion. recur will evaluate those
arguments, rebind them at the point of recursion and resume execution at that point.

The point of recursion is the nearest function ( defn , fn ) or loop form determined lexically.

recur must be in the tail position of the recursion point expression. The tail position is the point in the
expression where a return value would otherwise be determined.

recur does not bind & in variadic functions and in these situations an empty seq must be passed by
recur .

(defn count-up
[result x y]
(if (= x y)
result
(recur (conj result x) (inc x) y)))

(count-up [] 0 10)

[0 1 2 3 4 5 6 7 8 9]

Example: getting factorial of a positive integer:

(defn factorial
([n]
(factorial n 1))
([n acc]
(if (zero? n)
acc
(recur (dec n) (* n acc)))))

(factorial 10)

3628800

loop
(loop [bindings*] exprs*)

loop takes a vector of symbol value pairs followed by a variable number of expressions.

loop establishes a recursion point for a recur expression inside its body. loop provides an implicit
let for bindings.
The implicit let that loop provides binds each symbol to the init-expression. recur then binds new
values when returning the execution point to loop .

(defn count-up
[start total]
(loop [result []
x start
y total]
(if (= x y)
result
(recur (conj result x) (inc x) y))))

(count-up 0 10)

[0 1 2 3 4 5 6 7 8 9]

Example: getting factorial of a positive integer:

(defn factorial
[n]
(loop [n n
acc 1]
(if (zero? n)
acc
(recur (dec n) (* acc n)))))

(factorial 10)

3628800

trampoline
([f])
([f & args])

trampoline takes a function and a variable number of arguments to pass to that function.

trampoline allows for mutual recursion without consuming stack space proportional to the number of
recursive calls made.

If the return value of that function is a function, trampoline calls that function with no arguments. If the
return value is not a function, trampoline simply returns that value.

Since trampoline calls the returned functions with no arguments, you must supply an anonymous
function that takes no arguments and calls the function you wish to recur to. This is usually done with
anonymous function literals #()
(declare count-up1 count-up2) ;; see `declare` for why this is needed

(defn count-up1
[result start total]
(if (= start total)
result
#(count-up2 (conj result start) (inc start) total))) ;; returns an anonymous

(defn count-up2 [result start total]
(if (= start total)
result
#(count-up1 (conj result start) (inc start) total))) ;; returns an anonymous

;; delete #_ to run the example:
#_(trampoline count-up1 [] 0 10)

#'cljs.user/count-up2

for
([seq-exprs body-expr])

for takes a vector of pairs of [binding collection].

for allows for list comprehensions. for assigns each sequential value in the collection to the binding
form and evaluates them rightmost first. The results are returned in a lazy sequence.

for allows for explicit let, when and while through use of :let [] , :when (expression) , and :while
(expression) in the binding vector.

(for [x [1 2 3] y [4 5 6]]
[x y])

([1 4] [1 5] [1 6] [2 4] [2 5] [2 6] [3 4] [3 5] [3 6])

:when only evaluates the body when a truthy value is returned by the expression provided

(for [x [1 2 3] y [4 5 6]
:when (and
(even? x)
(odd? y))]
[x y])

([2 5])

:while evaluates the body until a falsey value is reached. Note that elements of the second collection
are bound to y before a falsey value of (< x 2) is reached in the following example. This demonstrates
the order of the comprehension.
(for [x [1 2 3] y [4 5 6]
:while (< x 2)]
[x y])

([1 4] [1 5] [1 6])

doseq
([seq-exprs & body])

doseq takes a vector of pairs of [binding collection] and then one or more expressions as the
body .

doseq is similar to for except it does not return a sequence of results. doseq is generally intended for
execution of side-effects in the body, and thus returns nil .

doseq supports the same bindings as for - :let , :when , :while . For examples of those, see for
above.

(doseq [x [1 2 3] y [4 5 6]]
(println [x y]))

[1 4]
[1 5]
[1 6]
[2 4]
[2 5]
[2 6]
[3 4]
[3 5]
[3 6]
nil

run!
([proc coll])

If you have a single collection to loop over, just for side-effects, and a single function to call on each
element, you might prefer to use run! instead of doseq . The following are equivalent:

(doseq [x [1 2 3]]
(println x))
(run! println [1 2 3])
iterate
([f x])

iterate takes a function and an argument to the function.

A lazy sequence is returned consisting of the argument then each subsequent entry is the function
evaluated with the previous entry in the lazy sequence. In other words, the function is applied repeatedly
to produce each new entry in the sequence.

Since it is an infinite sequence, you need to use take or similar to get a finite number of elements.

(take 10 (iterate inc 0))

(0 1 2 3 4 5 6 7 8 9)

reduce
([f coll])
([f val coll])

reduce takes a function, an optional initial value and a collection.

If an initial value is provided, reduce applies the function to that initial value and the first item in the
collection. The function is then applied to that result and the second item in the collection, and so on. If the
collection is empty, the initial value is returned (and the function is not called).

If an initial value is not provided, and the behavior is a bit more complicated:

If the collection is empty, the function is called with no arguments and the result is returned,
If the collection has one element, that element is returned, and the function is not called,
Otherwise, the function is called with the first two elements of the collection, and then with the result
of that call and the third element, and so on.

(reduce + 0 [1 2 3 4 5]) ; (+ 0 1) then (+ 1 2), (+ 3 3), (+ 6 4), (+ 10 5)

15

(reduce + 0 []) ; 0 -- + is not called

(reduce + [1 2 3 4 5]) ; (+ 1 2) then (+ 3 3), (+ 6 4), (+ 10 5)

15
(reduce + [1]) ; 1 -- + is not called

(reduce + []) ; 0 -- (+) is called and produces zero

reductions
([f coll])
([f val coll])

reductions takes a function, an optional initial value and a collection.

reductions returns a lazy sequence of the intermediate values that would be produced during calls to
reduce with the same arguments.

Like reduce , if no initial value is provided, and the collection is empty, the function is called with no
arguments and the result is the only value in the lazy sequence; if no initial value is provided, and the
collection has only one element, that element is the only value in the lazy sequence, and the function is
not called.

map
([f coll])
([f c1 c2])
([f c1 c2 c3])
([f c1 c2 c3 & colls])

map takes a function and one or more collections. map passes an item from each collection, in order, to
the function and returns a lazy sequence of the results.

The function provided to map must support an arity matching the number of collections passed. Due to
this, when using more than one collection, map stops processing items when any collection runs out of
items.

mapv
([f coll])
([f c1 c2])
([f c1 c2 c3])
([f c1 c2 c3 & colls])

mapv takes a function and one or more collections. mapv passes an item from each collection, in order,
to the function and returns a vector of the results. Unlike map , mapv is not lazy.

If mapv is called with a single collection, it will use a transient vector to build the result for efficiency.
If mapv is called with multiple collections, it will first call map on them and then turn the result into a
vector (using into [] ).

The function provided to mapv must support an arity matching the number of collections passed. Due to
this, when using more than one collection, mapv stops processing items when any collection runs out of
items, like map .

Collection and Sequence Modification


conj
([coll x])
([coll x & xs])

conj takes a collection and a variable number of arguments.

conj is short for "conjoin". As the name implies, conj returns the collection with those arguments
added.

Adding items to a collection occurs at different places depending on the concrete type of collection.

List addition occurs at the beginning of the list. This is because accessing the head of the list is a constant
time operation, and accessing the tail requires traversal of the entire list.

(conj '(1 2) 3)
;; ⇒ (3 1 2)

Vectors have constant time access across the entire data structure. `'conj' thusly appends to the end of a
vector.

(conj [1 2] 3)

[1 2 3]

Maps do not have guaranteed ordering, so the location that items are added is irrelevant. conj requires
vectors of [key value] pairs to be added to the map.

(conj {:a 1 :b 2 :c 3} [:d 4])

{:a 1, :b 2, :c 3, :d 4}

(conj {:cats 1 :dogs 2} [:ants 400] [:giraffes 13])

{:cats 1, :dogs 2, :ants 400, :giraffes 13}

Sets also do not have guaranteed ordering. conj returns a set with the item added. As the concept of
sets implies, added items will not duplicate equivalent items if they are present in the set.
(conj #{1 4} 5)

#{1 4 5}

(conj #{:a :b :c} :b :c :d :e)

#{:a :b :c :d :e}

empty
([coll])

empty takes a collection

empty returns an empty collection of the same type as the collection provided.

(empty [1 2 3])

[]

(empty {:a 1 :b 2 :c 3})

{}

assoc
([map key val])
([map key val & kvs])

assoc takes a key and a value and returns a collection of the same type as the supplied collection with
the key mapped to the new value.

assoc is similar to get in how it works with maps, records or vectors. When applied to a map or record,
the same type is returned with the key/value pairs added or modified. When applied to a vector, a vector is
returned with the key acting as an index and the index being replaced by the value.

Since maps and records can not contain multiple equivalent keys, supplying assoc with a key/value that
exists in the one will cause assoc to return modify the key at that value in the result and not duplicate the
key.

(assoc {:a 1} :b 2)

{:a 1, :b 2}
(assoc {:a 1 :b 45 :c 3} :b 2)

{:a 1, :b 2, :c 3}

(defrecord Hand [index middle ring pinky thumb])


(assoc (Hand. 3 4 3.5 2 2) :index 3.75)

{:index 3.75, :middle 4, :ring 3.5, :pinky 2, :thumb 2}

When using assoc with a vector, the key is the index and the value is the value to assign to that index in
the returned vector. The key must be <= (count vector) or a "IndexOutOfBoundsException" will occur.
assoc can not be used to add an item to a vector.

(assoc [1 2 76] 2 3) ;= [1 2 3]

[1 2 3]

;; index 5 does not exist. valid indexes for this vector are: 0, 1, 2
(assoc [1 2 3] 5 6)

Execution error.
ERROR: Error: Index 5 out of bounds [0,3]

dissoc
([map])
([map key])
([map key & ks])

dissoc takes a map and a variable number of keys.

dissoc returns a map with the supplied keys, and subsequently their values, removed. Unlike assoc ,
dissoc does not work on vectors. When a record is provided, dissoc returns a map. For similar
functionality with vectors, see subvec and concat .

(dissoc {:a 1 :b 2 :c 3} :b)

{:a 1, :c 3}

(dissoc {:a 1 :b 14 :c 390 :d 75 :e 2 :f 51} :b :c :e)

{:a 1, :d 75, :f 51}


;; note that a map is returned, not a record.
(defrecord Hand [index middle ring pinky thumb])
;; always be careful with the bandsaw!
(dissoc (Hand. 3 4 3.5 2 2) :ring)

{:index 3, :middle 4, :pinky 2, :thumb 2}

Information about a Collection or Sequence


count
([coll])

count takes a collection.

Returns a count of the number of items in a collection. An argument of nil returns 0.

(count "Hello")

(count [1 2 3 4 5 6 7])

(count nil)

Note that count does not return in constant time for all collections. This can be determined with
counted? . Keep in mind that lazy sequences must be realized to get a count of the items. This is often
not intended and can cause a variety of otherwise cryptic errors.

(counted? "Hello")

false

;; will be fully realized when using (count (range 10))


(counted? (range 10))

true
;; Constant time return of (count)
(counted? [1 2 3 4 5])

true

empty?
([coll])

empty takes a collection.

empty? returns true if the collection has no items, or false if it has 1 or more items.

(empty? [])

true

(empty? '(1 2 3))

false

Do not confuse empty? with empty . This can be a source of great confusion:

(if (empty [1 2 3]) ;; empty returns an empty seq, which is true! use empty? here
"It's empty"
"It's not empty")

"It's empty"

not-empty
([coll])

not-empty takes a collection.

not-empty returns nil if the collection has no items. If the collection contains items, the collection is
returned.

(not-empty '(:mice :elephants :children))

(:mice :elephants :children)


(not-empty '())

nil

Items in a Collection or Sequence


first
([coll])

first takes a collection.

first returns the first item in the collection. first returns nil if the argument is empty or is nil.

Note that for collections that do not guarantee order like some maps and sets, the behaviour of first
should not be relied on.

(first (range 10))

(first [:floor :piano :seagull])

:floor

(first [])

nil

rest
([coll])

rest takes a collection.

rest returns a seq of items starting with the second element in the collection. rest returns an empty
seq if the collection only contains a single item.

rest should also not be relied on when using maps and sets unless you are sure ordering is guaranteed.

(rest [13 1 16 -4])

(1 16 -4)
(rest '(:french-fry))

()

The behaviour of rest should be contrasted with next . next returns nil if the collection only has a
single item. This is important when considering "truthiness" of values since an empty seq is still a truthy
value but nil is not.

(if (rest '("stuff"))


(print "Does this print?")) ;; yes, it prints.

Does this print?nil


Robert is from an unknown location and enjoys giraffe migrations

;; NEVER FINISHES EXECUTION!


;; "done" is never reached because (rest x) is always a "true" value
(defn inf
[x]
(if (rest x)
(inf (rest x))
"done"))

get
([map key])
([map key not-found])

get takes an associative collection, a sequence of keys and an optional default value.

get returns the value for the specified key in a map or record, index of a vector or value in a set. If the
key is not present, get returns nil or a supplied default value.

;; val of a key in a map


(get {:a 1 :b 2 :c 3} :b)

;; index of a vector
(get [10 15 20 25] 2)

20

;; in a set, returns the value itself if present


(get #{1 10 100 2 20 200} 1)

1
;; returns nil if key is not present
(get {:a 1 :b 2} :c)

nil

;; vector does not have an _index_ of 4. nil is returned


(get [1 2 3 4] 4)

nil

(defrecord Hand [index middle ring pinky thumb])


(get (Hand. 3 4 3.5 2 2) :index)

get also supports a default return value supplied as the last argument.

;; index 4 does not exist. return default value


(get [1 2 3 4] 4 "Not Found")

"Not Found"

;; key :c does not exist, so return default value of 3


(get {:a 1 :b 2} :c 3)

contains?
([coll key])

contains? takes a collection and a key.

contains returns true if the provided key is present in a collection. contains is similar to get in that
vectors treat the key as an index. contains will always return false for lists.

(contains? {:a 1 :b 2 :c 3} :c)

true

;; true if index 2 exists


(contains? ["John" "Mary" "Paul"] 2)

true
;; false if index 5 does not exist
(contains? ["John" "Mary" "Paul"] 5)

false

;; "Paul" does not exist as an index


(contains? ["John" "Mary" "Paul"] "Paul")

false

;; lists are not supported. contains? won't traverse a collection for a result.
(contains? '(1 2 3) 0) ; false in ClojureScript, an exception in Clojure

false

keys
([map])

keys takes a map or record.

keys returns a sequence of the keys in a map or record.

(keys {1 "one" 2 "two" 3 "three"})

(1 2 3)

(defrecord Hand [index middle ring pinky thumb])


(keys (Hand. 2 4 3 1 2))

(:index :middle :ring :pinky :thumb)

vals
([map])

vals takes a map or record.

vals returns a sequence of vals in a map or record.

(vals {:meows 20 :barks 2 :moos 5})

(20 2 5)
(defrecord Hand [index middle ring pinky thumb])
(vals (Hand. 1 2 3 4 5))

(1 2 3 4 5)

take
([n coll])

take takes a number and a collection.

take returns a lazy sequence starting with the first value of the collection and n sequential items after
that.

If the number of items in the collection is less than the provided number, the entire collection is returned
lazily.

drop
([n coll])

drop takes a number and a collection.

drop returns a lazy sequence starting at the nth item of the collection.

take-while
([pred coll])

take-while takes a function that accepts a single-argument and a collection.

take-while returns a lazy sequence of sequential items until the function returns nil/false value for that
item.

(take-while pos? (range 5 -5 -1))

(5 4 3 2 1)

drop-while
([pred coll])

'drop-while` takes a function that accepts a single-argument and a collection.

drop-while returns a lazy sequence starting at the first item in the collection that the function returns
nil/false.
filter
([pred coll])

filter takes a function that accepts a single argument and a collection.

filter returns a lazy sequence of items for which the provided predicate produces a truthy value.
Contrast to remove .

(filter even? (range 10))

(0 2 4 6 8)

(filter #(if (< (count %) 5) %) ["Paul" "Celery" "Computer" "Rudd" "Tayne"])

("Paul" "Rudd")

When using sets with filter , remember that if nil or false is in the set and in the collection, then
the predicate will return falsey and the item will be omitted.

(filter #{:nothing :something nil false} [:nothing :something :things :someone ni

(:nothing :something)

filterv
([pred coll])

filterv takes a function that accepts a single argument and a collection.

filterv returns a vector of items for which the provided predicate produces a truthy value. Contrast to
remove .

(filterv even? (range 10))

[0 2 4 6 8]

(filterv #(if (< (count %) 5) %) ["Paul" "Celery" "Computer" "Rudd" "Tayne"])

["Paul" "Rudd"]

When using sets with filterv , remember that if nil or false is in the set and in the collection, then
the predicate will return falsey and the item will be omitted.
(filterv #{:nothing :something nil false} [:nothing :something :things :someone n

[:nothing :something]

keep
(keep f coll)

keep takes a function that accepts a single argument and a collection.

keep returns a lazy sequence of non-nil results of the function applied to each item in the collection in
sequence.

;; naive attempt: returns a sequence of true/false


(keep even? (range 10))

(true false true false true false true false true false)

;; return even? item or nil:


(keep #(when (even? %) %) (range 10))

(0 2 4 6 8)

(keep not-empty ["" "Sean" "" "Corfield" ""])

("Sean" "Corfield")

remove
([pred coll])

remove takes a function that accepts a single argument and a collection.

remove returns a lazy sequence of items that return false or nil for the provided predicate. Contrast
to filter .

(remove even? (range 10))

(1 3 5 7 9)

;; relative complement. probably useless?


(remove {:a 1 :b 2} [:h :k :z :b :s])

(:h :k :z :s)
When using sets with remove , remember that if nil or false is in the set and in the collection, then the
predicate will return itself: nil . This will cause that item to be included in the returned lazy sequence.

In this example, when nil and false are tested with the predicate, the predicate returns nil. This is because
if the item is present in the set it is returned.

(remove #{:nothing :something nil} [:nothing :something :things :someone nil fals

(:things :someone nil false :pigeons)

some
([pred coll])

some takes a function that accepts a single argument and a collection.

some will apply a predicate to each value in a collection until a non-false/nil result is returned then
immediately return that result.

Since collections are "true" values, this makes it possible to return the first result itself rather than simply
true .

(some even? [1 2 3 4 5])

true

;; predicate returns the value rather than simply true


(some #(if (even? %) %) [1 2 3 4 5])

Since maps can be used as functions, you can use a map as a predicate. This will return the value of the
first key in the collection that is also in the map.

(some {:a 1 :b 5} [:h :k :d :b])

Sets can also be used as functions and will return the first item in the collection that is present in the set.

(some #{4} (range 20))

every?
([pred coll])
every? takes a function that accepts a single argument and a collection.

every? returns true if the predicate returns true for every item in the collection, otherwise it returns false.

(every? even? (range 0 10 2))

true

;; set can be used to see if collection only contains items in the set.
(every? #{2 3 4} [2 3 4 2 3 4])

true

Processing Collections and Sequences


partition
([n coll])
([n step coll])
([n step pad coll])

partition takes a number, an optional step, an optional padding collection and a collection. If the
padding collection is provided, a step must be provided.

partition sequentially takes a provided number of items from the collection in sequence and puts them
into lists. This lazy sequence of lists is returned.

If a step is provided, the lists in the returned lazy sequence start at offsets in the provided collection of that
number items in the list.

If a padding collection is provided, the last item in the returned lazy sequence will be padded with the
padding collection to achieve the desired partitioning size.

If there is no padding collection provided and there is not enough items to fill the last list in the returned
lazy sequence, those items will be not used.

;; divide the sequence into pairs, the value 4 is dropped:


(partition 2 (range 5))

((0 1) (2 3))

;; staggered pairs can be useful (and the value 4 is included):


(partition 2 1 (range 5))

((0 1) (1 2) (2 3) (3 4))
;; divide the sequence into pairs and pad the last pair with -1:
(partition 2 2 [-1] (range 5))

((0 1) (2 3) (4 -1))

partitionv
([n coll])
([n step coll])
([n step pad coll])

partitionv is just like partition above, except it returns a lazy sequence of vectors instead of a lazy
sequence of lists.

partition-all
([n coll])
([n step coll])

partition-all takes a number, an optional step and a collection.

partition-all sequentially takes a provided number of items from the collection in sequence and puts
them into lists. This lazy sequence of lists is returned.

If a step is provided, the lists in the returned lazy sequence start at offsets in the provided collection of that
number items in the list.

If there are not enough items to fill the last list in the returned lazy sequence, the remaining items will be
used in the last list.

;; divide the sequence into pairs, the value 4 is not dropped:


(partition-all 2 (range 5))

((0 1) (2 3) (4))

partitionv-all
([n coll])
([n step coll])

partitionv-all is just like partition-all above, except it returns a lazy sequence of vectors instead
of a lazy sequence of lists.

filter
See: filter
filterv
See: filterv

remove
See: remove

for
See: for

map
See: map

mapv
See: mapv

remove
See: remove

empty?
See: empty

not-empty
See: not-empty

Function Composition and Application


juxt
([])
([f])
([f g])
([f g h])
([f1 f2 f3 & fs])

juxt takes a variable number of functions.

juxt returns a function that will return a vector consisting of the result of applying each of those functions
to a provided argument.

;; turn a sequence of database rows into a map from ID to row:


(into {} (map (juxt :id identity)) [{:id 1 :name "Sean"} {:id 2 :name "Jay"}])

{1 {:id 1, :name "Sean"}, 2 {:id 2, :name "Jay"}}


comp
([])
([f])
([f g])
([f g h])
([f1 f2 f3 & fs])

comp takes a variable number of functions.

comp returns a function that will return the result of applying the rightmost function to the provided
argument, then the second rightmost function to the result of that etc.

(let [cf (comp f g h)]


(cf x)) ; the same as (f (g (h x)))

fnil
([f x])
([f x y])
([f x y z])

fnil takes a function and one to three arguments.

fnil returns a function that replaces any nil`` arguments with the provided values. fnil` only
supports supports patching 3 arguments, but will pass any arguments beyond that un-patched.

(defn say-info [name location hobby]


(println name "is from" location "and enjoys" hobby))

(def say-info-patched (fnil say-info "Someone" "an unknown location" "Clojure"))

(say-info-patched nil nil nil)

Someone is from an unknown location and enjoys Clojure


nil

(say-info-patched "Robert" nil "giraffe migrations")

nil

apply
([f args] [f x args] [f x y args] [f x y z args] [f a b c d & args])

apply takes a variable number of arguments and a collection.


apply effectively unrolls the supplied args and a collection into a list of arguments to the supplied
function.

(str ["Hel" "lo"])

"[\"Hel\" \"lo\"]"

(apply str ["Hel" "lo"]) ;; same as (str "Hel" "lo")

"Hello"

apply prepends any supplied arguments to the form as well.

(map + [[1 2 3] [1 2 3]]) ;; This attempts to add 2 vectors with +

([1 2 3] [1 2 3])

(apply map + [[1 2 3] [1 2 3]]) ;; same as (map + [1 2 3] [1 2 3])

(2 4 6)

(apply + 1 2 3 [4 5 6]) ;; same as (+ 1 2 3 4 5 6)

21

Note that apply can not be used with macros.

->
([x])
([x form])
([x form & more])

-> takes a value and optionally one or more expressions.

-> takes the first argument and inserts it as the second item in the next form, or creates a list with the
first argument as the second item. The return value of that expression is inserted as the second item in the
next form, making a list if necessary. This continues until all expressions are evaluated and the final value
is returned.
(-> 5
(inc)
(- 3)
(* 2))
;; ⇒ 6
(-> {:a 1 :b 2}
:b
(inc))
;; ⇒ 3

->>
([x])
([x form])
([x form & more])

->> takes a value and optionally one or more expressions.

->> takes the first argument and inserts it as the last item in the next form, or creates a list with the first
argument as the last item. The return value of that expression is inserted as the last item in the next form,
making a list if necessary. This continues until all expressions are evaluated and the final value is
returned.

(->> (range 5) ; (0 1 2 3 4)
(map inc) ; (1 2 3 4 5)
(filter even?) ; (2 4)
(reduce +)) ; (+ 2 4)
;; ⇒ 6

Associative Collections
get-in
([m ks] [m ks not-found])

get-in takes an associative collection, a sequence of keys and an optional default value.

get-in takes the first value in the sequence of keys and retrieves the value, then applies each
subsequent key to to the most recently returned value and returns the final result. If any key is not present
when evaluated then either nil, or a provided default value is returned.

(get-in {:profile {:personal {:age 28}}} [:profile :personal :age])

28
update-in
([m [k & ks] f & args])

update-in takes an associative collection, a sequence of keys, a function and optional arguments to
supply to that function.

update-in takes the first value in the sequence of keys and retrieves the value, then applies each
subsequent key to to the most recently returned value. The function and optional arguments are applied to
the value and a new nested collection is returned with the key having the result of that function.

update-in will create new hash-maps if a key in the sequence of keys does not exist. The returned
collection will have a nested structure correlating to the provided sequence along with the result of the
function and optional arguments as the value of the final key.

(update-in {:profile {:personal {:age 28}}} [:profile :personal :age] inc)

{:profile {:personal {:age 29}}}

assoc-in
([m [k & ks] v])

assoc-in takes an associative collection, a sequence of keys and a value.

assoc-in takes the first value in the sequence of keys and retrieves the value, then applies each
subsequent key to to the most recently returned value. The final key is assigned the provided value and a
new nested collection is returned.

assoc-in will create new hash-maps if a key in the sequence of keys does not exist. The returned
collection will have a nested structure correlating to the provided sequence along with the provided value
as the value of the final key.

(assoc-in {:profile {:personal {:age 28}}} [:profile :personal :location] "Vancou

{:profile {:personal {:age 28, :location "Vancouver, BC"}}}

select-keys
([map keyseq])

select-keys takes an associative collection and a sequence of keys.

select-keys returns a map containing only the entries that have a key which is also present in the
sequence of keys.
(select-keys {:a 1 :b 2 :c 3} [:a :b])

{:a 1, :b 2}

keys
See: keys

vals
See: vals

get
See: get

assoc
See: assoc

dissoc
See: dissoc

Namespace Functions
ns, require, use, import, refer
Please see the Namespace guide (/articles/language/namespaces/)

Reference Types
ref, atom, var, agent
Please see the Concurrency and Parallelism Guide (/articles/language/concurrency_and_parallelism/)

deref, swap!, reset!, dosync, alter, commute, binding


Please see the Concurrency and Parallelism Guide (/articles/language/concurrency_and_parallelism/)

Contributors
Robert Randolph [email protected] (mailto:[email protected]) (original author) Michael Klishin
[email protected] (mailto:[email protected]) Nguyễn Hà Dương [email protected]
(mailto:[email protected])

« Language: Functions (/articles/language/functions/) || Language: Collections and Sequences »


(/articles/language/collections_and_sequences/)
Links
About (/articles/about/)
Table of Contents (/articles/content/)
Getting Started (/articles/tutorials/getting_started/)
Introduction to Clojure (/articles/tutorials/introduction/)
Clojure Editors (/articles/tutorials/editors/)
Clojure Community (/articles/ecosystem/community/)
Basic Web Development (/articles/tutorials/basic_web_development/)
Language: Functions (/articles/language/functions/)
Language: clojure.core
Language: Collections and Sequences (/articles/language/collections_and_sequences/)
Language: Namespaces (/articles/language/namespaces/)
Language: Java Interop (/articles/language/interop/)
Language: Polymorphism (/articles/language/polymorphism/)
Language: Concurrency and Parallelism (/articles/language/concurrency_and_parallelism/)
Language: Macros (/articles/language/macros/)
Language: Laziness (/articles/language/laziness/)
Language: Glossary (/articles/language/glossary/)
Ecosystem: Library Development and Distribution (/articles/ecosystem/libraries_authoring/)
Ecosystem: Web Development (/articles/ecosystem/web_development/)
Ecosystem: Generating Documentation (/articles/ecosystem/generating_documentation/)
Building Projects: tools.build and the Clojure CLI (/articles/cookbooks/cli_build_projects/)
Data Structures (/articles/cookbooks/data_structures/)
Strings (/articles/cookbooks/strings/)
Mathematics with Clojure (/articles/cookbooks/math/)
Date and Time (/articles/cookbooks/date_and_time/)
Working with Files and Directories in Clojure (/articles/cookbooks/files_and_directories/)
Middleware in Clojure (/articles/cookbooks/middleware/)
Parsing XML in Clojure (/articles/cookbooks/parsing_xml_with_zippers/)
Growing a DSL with Clojure (/articles/cookbooks/growing_a_dsl_with_clojure/)

Copyright © 2024 Multiple Authors


Powered by Cryogen (https://cryogenweb.org)

You might also like