Functions
In Clojure functions are treated as first class citizens i.e. function is treated like any other value and can be passed over. This allows building higher order functions.
Its common in Clojure to have pure functions, i.e. functions with no side effects
Anonymous functions
fn
creates an anonymous function with named parameters and body e.g.
(fn [message] (print message))
declares a function without name, one argumentmessage
andprint message
as body
There can be zero or more arguments in the arguments vector and there can be one or more expressions in the body
We cant refer to the anonymous function in other parts of the code. But we can invoke a fn
(anonymous function)
in function position e.g. ((fn [message] (print message)) "Hello World!")
Defining Named functions using defn
;; Define a messenger function
(def messenger (fun [msg] (print msg)))
;; Other way to do the same
(defn messenger [msg] (print msg))
;; calling the function
(messenger "Hello World!")
defn
is a short hand for saying I’am defining a function
let
let
binds symbol to immutable values. Values can be literals or expressions- Bound symbols are availabel in the lexical scope
(defn messenger [msg]
( let [ a 7
b 5
c (capitalize msg)]
(println a b c)
) ; end of let scope
) ; end of function
Arity
Arity means the number of arguments a function takes
- Functions can be overloaded by arity
- Each arity is a
list:([args*] body*)
(defn messenger
;; no args function which calls one arg function
([] (messenger "Hello Wrold !"))
;; one arg function
([msg] (println msg)))
(messenger) ;; "Hello world"
(messenger "Hello Class") ;; "Hello Class"
Variadic functions - functions with variable number of arguments
- Variadic function is of indefinite arity
- Only one allowed when overloading on arity
&
symbol in params- Next param collects all remaining args
- Collected args are represented as sequence
(defn messenger [greeting & who]
(print greeting who))
(messenger "Hello" "World" "Class")
Apply
- Invokes function on arguments
- Final argument is a sequence
- “Unpacks” remaining arguments from sequence
(let [f print
a 1
b 2
more '(3 4)]
(apply f a b more))
(defn messenger [greeting & who] (apply print greeting who))
(messenger "Hello" "World" "Class")
;; Hello World Class
Closure
(defn messenger-builder [greeting]
(fn [who] (print greeting who)))
(def helloer (messenger-builder "Hello"))
(helloer "World!")
(defn messenger-builder [greeting]
(fn [who] (print greeting who)))
(defn helloer [] (messenger-builder "Hello"))
((helloer) "World!")
Both are same versions of the code. One uses def
and other users defn
Invoking Java Code
- Instantiation
(Widget. "foo")
is same asnew Widget("foo")
- Instance method
(.nextInt rnd)
is same as - Instance field
(.-field object)
is same asobject.field
- Static method
(Math/sqrt 25)
is same asMath.sqrt(25)
- Static field
Math/PI
is same asMath.PI
Method Chaining
(.. person getAddress getZipCode)
is same as (.getZipcode (.getAddress person))
is same as java version : person.getAddress().getZipCode()
Terse form #()
for short functions
#(.length %)
is same as (fn [obj] (.length obj))`