Clojure - Functions
Functions
Functions are a primary building block in Clojure. They can be used to craft complex programs from small and simple blocks.
Calling functions
1(+ 1 2 3 4)
2(* 1 2 3 4)
3(first [1 2 3 4])
In FP languages we treat functions as first class citizens meaning we can use them
like any other datatype. This allows us to pass them to other functions making higher order functions -
functions that take functions as parameters. An example of such function would be map which creates
a new list by applying a function to each member of a collection.
1(map inc [0 1 2 3])
2; => [1 2 3 4]
Defining functions
Function definitions are composed of five parts:
defn- function name
- an optional docstring
- parameters listed in brackets
- function body
The Docstring
Docstring represents a useful way to describe and document code. Dostrings can be viewed in
REPL with (doc fn-name).
Parameters and Arity
Clojure functions support arity overloading meaning one function can be defined to do different things depending on the number of arguments passed to it.
1(defn multi-arity
2 ([first-arg second-arg]
3 (do-thing first-arg second-arg))
4 ([first-arg]
5 (do-thing first-arg)))
Clojure allows defining of variable-arity functions by including a rest parameter(&)
1(defn greet
2 [name]
3 (str "Hello, " name " !"))
4
5(defn greet-many
6 [& people]
7 (map greet people))
8
9(greet-many "Bill" "Anne")
10; => ("Hello, Bill !" "Hello, Anne !")
Destructuring
Destructuring is used to concisely bind names to values within a collection.
1(defn first-thing
2 [[f]]
3 f)
4
5(first-thing [1 2 3 4])
6; => 1
Maps can also be destructured in a similar way.
1(defn greet-full
2 [{name :name surname :surname}]
3 (str "Hello, " name " " surname " !"))
4
5(greet-full {:name "Bill" :surname "Clinton"})
6; => "Hello Bill Clinton !"
7
8; Shorter syntax
9(defn greet-full
10 [{:keys [name surname]}]
11 (str "Hello, " name " " surname " !"))
Anonymous Functions
Functions that don’t have names are called anonymous functions. In Clojure we can define them in two ways:
1(fn [x] (* x 3))
1#(* % 3)
The percent sign indicated the argument passed to the function. When a anonymous function takes multiple parameters we can distinguish them like this: %1, %2, %3 …
Returining Functions
Functions can return other functions and the returned functions are closures meaning they can access all the variables that were in scope when the function was created.
1(defn inc-maker
2 [inc-by]
3 #(+ % inc_by))
4
5(def inc3 (inc-maker 3))
6
7(inc3 7)
8; => 10