In this section, we want you to tackle a new programming language, Clojure. This introduction covers defining functions in clojure, calling them, composing simpler functions into a higher order function etc.
We want you to understand the syntax of the language, experiment with writing some new functions.
You can write clojure on a simple online editor http://app.klipse.tech to try out the examples
A clojure function has this form:
(defn <function-name> [<arg-list>]
body)
You can call this function like:
(<function-name> arg1 arg2)
For example, here's an increment function:
(defn increment [a]
(+ a 1))
(increment 6) ;; returns 7
(defn sum [a b]
(+ a b))
(sum 40 2) ;; returns 42
Note that in clojure, we use prefix notation for calling functions.
(+ 1 2 3) ;;prefix, will run in your editor
1 + 2 + 3 ;;infix, will give error
sum (1 2 3) ;; also will give error
Square brackets are used to write vectors in clojure (arrays are called vectors in clojure)
[1 2 3 4] ;; no commas are required, separated by space
["a" "b" "c" "d"]
Here are some common functions used in clojure:
+, - , *
operators are used as functions
(+ 2 3) ;;5
(- 2 3) ;;-1
(* 2 3) ;;6
some predicate (returning boolean) functions
(< 1 2) ;;true
(= 1 (- 2 1)) ;;true
string operations
(str "Hello" "Nilenso" "!") ;; returns "HelloNilenso!"
map
is used to iterate over sequences, like vectors
A map
takes a function and applies it to each of the elements in the sequence:
(map <function> <vector>)
For example, here is how I would increment every element in a vector
(map increment [1 2 3 4 5]) ;; returns [2 3 4 5 6]
Similarly, filter
runs a function on every element of a sequence and keeps that element if the function returns true.
(filter <predicate-fn> vector)
(filter zero? [-1 0 1 0 2]) ;; returns [0 0]
(filter (fn [v] (> v 2)) [1 2 3 2 4]) ;; returns [3 4]
The last example of filter used an anonymous function (has no name!).
(fn [a b] (- a b)) ;; returns a - b
Two ways of writing the above filter function. Both are equivalent but the first way is more concise.
(filter (fn [v] (> v 2)) [1 2 3 2 4]) ;; returns [3 4]
;;---------------------------
(defn greater-than-two [v] (> v 2))
(filter greater-than-two [1 2 3 2 4]) ;; returns [3 4]
More examples:
(map (fn [element] (sum element 5)) [1 2 3]) ;;returns [6 7 8]
reduce
is another commonly used function that performs an aggregation, or "reduction" over a sequence.
It takes a function, an initial value, and a sequence as input. Often the result is a single value. You can read more about it here: https://clojuredocs.org/clojure.core/reduce. Here are a couple of examples:
(reduce <function> <initial-val> vector)
(+ 1 2) ;; returns 3
(reduce + 0 [1 2 3 4 5]) ;; returns 15
(reduce + 10 [1 2 3 4 5] ;; returns 25
(reduce
(fn [accumulator val]
(* accumulator val))
1
[1 2 3 4 5 6 7]) ;; returns 5040