2. ● Clojure is a Functional Lisp (List Processing) which runs on JVM.
● It extends the principle of Code-as-Data system to include Maps and Vectors.
Everything in clojure is written inside a data structure referred to as the
S-expressions, i.e nested lists.
Eg: (/ 4 (+ 1 2)) => ?
● Clojure is a Functional Lisp (List Processing) which runs on JVM.
● It extends the principle of Code-as-Data system to include Maps and Vectors.
Everything in clojure is written inside a data structure referred to as the
S-expressions, i.e nested lists.
Eg: (/ 4 (+ 1 2)) => ?
Function Name Arguments
● Every operation in clojure is done using a Post-Fix notation
3. ● Experimenting with clojure is quite easy. In order to get started with
clojure you need to follow the instructions on http://leiningen.org/ to
set up clojure environment on your system. Leningen is used for
project automation.
● Most popular IDE used for clojure is LightTable which can be
download from http://www.lighttable.com/
● You can fire up clojure's repl on linux terminal using:
lein repl or you can directly use a Live REPL in LightTable.
● You can also use clojure in Eclipse using CounterClockwise plugin.
● Everything that you need to know about clojure can be found in the
clojure cheatsheet at the following url: http://clojure.org/cheatsheet
4. ● Even though a lot of parentheses can confuse programmers at first,
LightTable(IDE) can make programming in clojure really easy. A sample of
what usage of parentheses I'm talking about:
(filter #(if(zero? (rem % 3)) true) (map #(+ % 1) (range 10)))
=> ?
● The above code in LightTable should look something like this:
● Last line of a function can return another function, i.e a Higher Order
Function as illustrated in the following example:
(defn attribute [who?]
(if (= who? "superman")
#(str "Superman " %)
(fn[x] (str "Human " x))))
((attribute "superman") "Flying") => "Superman Flying"
7. Concept of truthy and falsy
Everything in clojure is true except false or nil
So,
(if nil
“Yee! True”
“Huh! False”) => “Huh! False”
8. Data Structures
● Clojure supports a number of data structures:
Lists, Vectors, Maps, Sets
● All clojure data structures are persistent data structures. Internally
they're implemented as a tree.
● Simplest way to define these data structures:
'(1 2 3) defines a list
[1 2 3] defines a vector
#{1 2 3} defines a set
{:1 “one” :2 “two”} defines a map
9. Nesting
● Searching and updating nested structures is very easy.
● Searching:
(def n {:india {:newdelhi {:knoldus {:address "30/29, 1st Floor, East Patel Nagar"}}}
:usa {:california {:knoldus {:address "743, Catamaran Street "}}}})
user=> (get-in n [:india :newdelhi])
Returns {:knoldus {:address "30/29, 1st Floor, East Patel Nagar"}}
● Updating:
(assoc-in n [:india :newdelhi :knoldus :number] 911142316525)
Returns {:india {:newdelhi {:knoldus {:number 911142316525, :address "30/29, 1st Floor, East Patel
Nagar"}}}, :usa {:california {:knoldus {:address "743, Catamaran Street "}}}}
● Remember that the value of “n” hasn't changed in any case.
10. Threading Operators
The previous code that we used:
(filter #(if(zero? (rem % 3)) true) (map #(+ % 1) (range 10)))
Is same as:
(->> (range 10)
(map #(+ % 1))
(filter #(if (zero? (rem % 3)) true)))
The threaded version is much cleaner
11. Threading Operators
In Nested structures example that we used:
(def n {:india {:newdelhi {:knoldus {:address "30/29, 1st Floor, East Patel Nagar"}}}
:usa {:california {:knoldus {:address "743, Catamaran Street "}}}})
We can use:
(-> n :india :newdelhi :knoldus :address)
Instead of:
(:address (:knoldus (:newdelhi (:india n))))
13. Binding Form - let
● We use the “let” form to bind data structures to symbols.
● Example:
(let [x 10
y 11
m (* x y)]
m)
user=> m
14. Binding Form - let
● We can also use let binding for destructuring:
● (defn index-sum [v & i]
(let [[x :as ind] (map #(get v %) i)]
(reduce + ind)))
(index-sum [1 2 3 4 5 6 7 8 9] 1 3 5) => ?
15. Built-in Parallelism
● “map” function will take more time as compared to the “pmap” function:
(time (doall (map (fn[x] (Thread/sleep 3000) (+ x 5)) (range 1 5))))
=> "Elapsed time: 12000.99432 msecs"
(6 7 8 9)
(time (doall (pmap (fn[x] (Thread/sleep 3000) (+ x 5)) (range 1 5))))
=> "Elapsed time: 3002.989534 msecs"
(6 7 8 9)
16. Futures
● Futures can be used to send any calculation intensive work in the
background while continuing with some other work.
● Defining futures:
(def f (future some-calculation-intensive-work))
● Example:
(defn show-result[]
;;do things
(def f (future some-calculation-intensive-work))
;;prepare gui to display result
@f) ;;wait until the result is returned
17. Atoms, refs and agents
● Atoms, refs and agents are the three options available for maintaining non-
local mutable state in clojure
➔ Atoms are for Uncoordinated Synchronous access
to a single Identity.
➔ Refs are for Coordinated Synchronous access
to Many Identities.
➔ Agents are for Uncoordinated Asynchronous access
to a single Identity.
18. Atoms
● Defining an atom:
(def a (atom {:a 1}))
● Getting the value stored in an atom:
(deref a) or @a
● Changing the value of an atom:
(swap! a #(assoc % :b 2)) => {:a 1 :b 2}
or
(reset! a 0) => Exception or changed value?
20. Agents
● Can be useful in fork/join solutions.
● Defining an agent:
(def a (agent 0))
● Dispatching actions to an agent:
(dotimes [x 3] (send-off a (fn[x] (Thread/sleep 3000) (inc x))))
@a => ?
● In case we want to wait until the above code snippet has finished processing,
we can use:
(await a)
25. Protocols
● Dataype are used to implement protocols or interfaces.
(defprotocol Dialogue
(deliver-dialogue [d]))
(defrecord Where? [place]
Dialogue
(deliver-dialogue [d] (str "One does not simply walk into " place)))
● (def LOR (Where?. "Mordor"))
(deliver-dialogue LOR)
=> "One does not simply walk into Mordor"