3. Clojure History
Started in 2007
Original author (and BDFL) Rich Hickey
Currently version 1.1 (1.2 expected within the next
month)
Available under Eclipse Public License
“The Eclipse Public License is designed to be a
business-friendly free software license and
features weaker copyleft provisions than
contemporary licenses such as the GNU General
Public License (GPL).”
7. Syntax
That’s it. There is no other syntax[1].
Data structures are code.
Homoiconic
All data literals stand for themselves
except:
Lists
Symbols
[1]: Technically, there are other special symbols for shortcutting syntax provided for the developer, but no other necessary syntax
8. Lists
(+ 1 1) ; => 2
(+ 1 2 3) ; => 6
(+ 1 2 (+ 3 4)) ; => 10
(class “foo”) ; => java.lang.String
(first [:a :b :c]) ; => :a
(rest ‘(“foo” “bar” “baz”)) ; => (“bar” “baz”)
The ‘ tells the reader not to evaluate the first element as a function
‘(1 2 3) is shorthand for (quote (1 2 3))
11. Operating on
Collections
Collections are the main datastructure in
Clojure
A collection can be a list, a vector, a map or a
set
Some example collection functions:
first, second, last, count, reverse, concat,
conj, contains?, map, reduce, apply, filter,
some, remove, every?, nth, into, doall,
repeat, repeatedly, range,
12. Laziness
Sequences can be lazy, which allows them to be
infinite:
(cycle [1 2 3]) ; => (1 2 3 1 2 3 1 2 3 ...)
(repeat :a) ; => (:a :a :a :a :a :a :a ...)
When using lazy sequences, processing does not
occur until the sequence is realized.
(class (repeat :a)) ; => clojure.lang.LazySeq
Realize (part of) a lazy sequence:
(take 5 (repeat 42)) ; => (42 42 42 42 42)
13. More laziness
Can do neat things with infinite
sequences:
(filter even? (iterate inc 1)) ; => (2 4 6 8...)
Lazily read lines from a file:
(read-lines “/tmp/foo.txt”)
Lines aren’t read until they are used in
the returned list
14. Java interop
(.toLowerCase “EMC”) ; => “emc”
(<method> <object> [<arg1> <arg2> ...])
(StringBuffer. “foo” ) ; => #<StringBuffer foo>
(Integer/parseInt “5”) ; => 5
(.contains “My spoon is too big.” “spoon“) ; => true
(javax.swing.JOptionPane/showMessageDialog nil "Sup!")
“Clojure is a better Java than Java”
15. Java datastructures
Anything that’s a Collection (or array) in Java can easily be
treated (or converted) as a Clojure collection
(first (.split “This is a sentence” “ “)) ; => “This”
(import ‘java.util.ArrayList)
(def foo (ArrayList. [1 2 3])) ; => #<ArrayList [1, 2, 3]>
(seq foo) ; => (1 2 3)
(vec foo) ; => [1 2 3]
18. Functional
Programming
Functions are intended to be side-effect free
They take values and return values
Same argument, same result
No notion of time
Easy to add concurrency to the mix sanely
Testing is easier because there is no state
Having no side effects isn’t always possible (io,
mutable java objects)
19. Concurrency
Locks are bad
Clojure’s defining concurrency feature is STM
Gives you ACI out of ACID
Atomicity
Consistency
Isolation
Immutability is what makes this possible
4 methods for changing data concurrently:
24. Concurrency (Agents)
(def x (agent 0))
@x ; => 0
(defn increment [c n] (+ c n))
(send x increment 5) ; @x -> 5
(send x increment 10) ; @x -> 15
25. Macros
(defmacro def-name-filter
[n r]
(let [docstring (str "Given a list of people maps, filter " n " in a list.")]
`(defn ~n
~docstring
[elements#]
(filter (fn [t#] (re-find ~r (:name t#))) elements#))))
(def-name-filter foo-filter #"^foo")
(def people [{:name "pat"} {:name "foobar"} {:name "foo"} {:name "bar"}])
(doc foo-filter)
; => Given a list of people maps, filter foo-filter in a list.
(foo-filter people)
; => ({:name "foobar"} {:name "foo"})
28. Much More
Polymorphism/multimethods
Pre and Post conditions for functions
Futures, Promises
Watchers
Bindings/Transients
Metadata features
Compilation
Clojure-in-Clojure
So much more!