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 (including images & stylesheets). The source is available on Github.

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))

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))

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

let bindings are immutable and can be destructured.

See: Sections about destructuring in Introduction and Functions 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 block
  (vector my-secret-number cljs.user/my-secret-number my-secret-string))  

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 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!"))

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.

See the def Special Form 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'
(if nil "second" "third")
(if (< 10 9) "second" "third") ; (< 10 9) returns false
; seq returns nil for an empty sequence, 
; so the third expression (defaulted to nil) is returned
(if (seq '()) "second")
(if (nil? (= 1 2)) "second" "third") ; differentiate between nil and false if needed
; 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."))

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)
;; (< 10 11) is true so both expressions are evaluated and the last value returned
(when (< 10 11) (println "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).

(macroexpand '(when (< 3 4) (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)

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 function

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

;; delete #_ to run the example:
#_(trampoline count-up1 [] 0 10)
;; ⇒ [0 1 2 3 4 5 6 7 8 9]

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
;; ⇒ 0
(reduce + [1 2 3 4 5]) ; (+ 1 2) then (+ 3 3), (+ 6 4), (+ 10 5)
;; ⇒ 15
(reduce + [1]) ; 1 -- + is not called
;; ⇒ 1
(reduce + []) ; 0 -- (+) is called and produces zero
;; ⇒ 0

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])
;; ⇒ {:d 4, :a 1, :c 3, :b 2}
(conj {:cats 1 :dogs 2} [:ants 400] [:giraffes 13])
;; ⇒ {:giraffes 13, :ants 400, :cats 1, :dogs 2}

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 :c :b :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)
;; ⇒ {:b 2, :a 1}
(assoc {:a 1 :b 45 :c 3} :b 2)
;; ⇒ {:a 1, :c 3, :b 2}
(defrecord Hand [index middle ring pinky thumb])
(assoc (Hand. 3 4 3.5 2 2) :index 3.75)
;; ⇒ #user.Hand{: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]
;; index 5 does not exist. valid indexes for this vector are: 0, 1, 2
(assoc [1 2 3] 5 6)
;; IndexOutOfBoundsException   clojure.lang.PersistentVector.assocN (PersistentVector.java:136)

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, :f 51, :d 75}
;; 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")
;; ⇒ 5
(count [1 2 3 4 5 6 7])
;; ⇒ 7
(count nil)
;; ⇒ 0

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))
;; ⇒ false
;; 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))
;; ⇒ 0
(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.
;; 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)
;; ⇒ 2
;; 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)
;; ⇒ 3

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)
;; ⇒ 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

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})
;; ⇒ (5 2 20)
(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 nil false :pigeons])
;; ⇒ (: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 nil false :pigeons])
;; ⇒ [: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 false :pigeons])
;; ⇒ (: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])
;; ⇒ 2

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])
;; ⇒ 5

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))
;; ⇒ 4

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"}])

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
(say-info-patched "Robert" nil "giraffe migrations")
;; ⇒ Robert is from an unknown location and enjoys giraffe migrations

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\"]" ;; not what we want, str is operating on the vector
(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 +
;; ClassCastException   java.lang.Class.cast (Class.java:2990)
(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] "Vancouver, BC")
;= {:profile {:personal {:location "Vancouver, BC", :age 28}}}

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])
;= {:b 2, :a 1}

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

Reference Types

ref, atom, var, agent

Please see the Concurrency and Parallelism Guide

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

Please see the Concurrency and Parallelism Guide

Contributors

Robert Randolph audiolabs@gmail.com (original author) Michael Klishin michael@defprotocol.org Nguyễn Hà Dương cmpitg@gmail.com