clojure class
DESCRIPTION
TRANSCRIPT
![Page 1: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/1.jpg)
Better Living Through Clojure
MIT IAPJanuary 14-15, 2014
![Page 2: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/2.jpg)
Bhaskar (Buro) Mookerji (‘09 VIII , ‘11 VI/MEng)
David Greenberg (‘11 XVIII-C)
Aysylu Greenberg (‘12 VI-2)
We are ….
![Page 3: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/3.jpg)
Today’s agenda includes...● Clojure Overview● Syntax: Everything is Data● Functions● Flow Control● Collections● Sequences
![Page 4: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/4.jpg)
... and tomorrow: ● Testing● Concurrency● Polymorphism● JVM Interop● Performance● Tooling● Interesting Problems Solved by Clojure● Our Projects
![Page 5: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/5.jpg)
Clojure Overview
![Page 6: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/6.jpg)
Rationale and Philosophy
● First released by Rich Hickey in 2007○ Expressive functional programming with Lisp○ Designed for concurrency use by default○ Embedded in an existing platform
● Robust, practical, high-performance ● Simple abstractions backed by powerful
ideas
![Page 7: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/7.jpg)
● Complacency breeds incidental complexity○ Large programs are difficult to understand○ Scope of effects are difficult to reason about○ Concurrency: holy crap.
● “Object-oriented programming is overrated”
The familiar solutions are complex
![Page 8: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/8.jpg)
Clojure is a Lisp
About the use of language: it is impossible to sharpen a pencil with a blunt axe. It is equally vain to try to do it with ten blunt axes instead.
- Edsger Dijkstra How do we tell truths that might hurt?, EWD498
(Actually John McCarthy.)
![Page 9: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/9.jpg)
Clojure is a Lisp
● LISP: code=data, few primitives, abstraction○ Local maximum in the hierarchy of expression
● Dynamically typed and compiled, interpreted● Syntactic abstraction through macros● Clojure:
○ Extends code-as-data to new data structures○ Modernizes LISP with new ideas from existing
functional languages
![Page 10: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/10.jpg)
Clojure is Functional and Dynamic
● Functions are first-class● All data structures are immutable, persistent,
recursive, and support heterogeneous types● Well-defined concurrent behavior● Strict typing (i.e., Haskell, OCaml) is not
everyone nor needed for every application
![Page 11: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/11.jpg)
Clojure Runs on the JVM (and Javascript!)
● OS independent● JVM: Well-supported, existing platform, lots
of libraries/platforms● Static types and safety● Garbage collection and a great compiler● Clojurescript:
○ Javascript as the platform: runs everywhere
![Page 12: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/12.jpg)
Syntax: Everything is Data
![Page 13: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/13.jpg)
Atomic Literals22 ;; Long
12345678901 ;; BigInt
1.34 ;; Double
1.34M ;; BigDecimal
22/3 ;; Ratio
true ;; boolean
“derp” ;; String
\d \e \r \p ;; Character
#”[0-9]+” ;; Regex
:derp, ::derp ;; Keyword
nil ;; null
![Page 14: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/14.jpg)
Atomic Literals22 ;; Long
12345678901 ;; BigInt
1.34 ;; Double
1.34M ;; BigDecimal
22/2 ;; Ratio
true ;; boolean
Evaluating literals in the REPL:
“derp” ;; String
\d \e \r \p ;; Character
#”[0-9]+” ;; Regex
:derp, ::derp ;; Keyword
nil ;; null
user=> 22 ;; Read ;; Eval22 ;; Printuser=> ;; Loop
![Page 15: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/15.jpg)
Atomic Literals22 ;; Long
12345678901 ;; BigInt
1.34 ;; Double
1.34M ;; BigDecimal
22/2 ;; Ratio
true ;; boolean
Evaluating expressions:
“derp” ;; String
\d \e \r \p ;; Character
#”[0-9]+” ;; Regex
:derp, ::derp ;; Keyword
nil ;; null
user=> (+ 2 2) ;; Read ;; Eval4 ;; Printuser=> ;; Loop
![Page 16: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/16.jpg)
Atomic Literals22 ;; Long
12345678901 ;; BigInt
1.34 ;; Double
1.34M ;; BigDecimal
22/2 ;; Ratio
true ;; boolean
Evaluating expressions:
“derp” ;; String
\d \e \r \p ;; Character
#”[0-9]+” ;; Regex
:derp, ::derp ;; Keyword
nil ;; null
user=> ::derp ;; Read ;; Eval:user/derp ;; Printuser=> ;; Loop
![Page 17: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/17.jpg)
Atomic Literals22 ;; Long
12345678901 ;; BigInt
1.34 ;; Double
1.34M ;; BigDecimal
22/2 ;; Ratio
true ;; boolean
Evaluating expressions:
“derp” ;; String
\d \e \r \p ;; Character
#”[0-9]+” ;; Regex
:derp, ::derp ;; Keyword
nil ;; null
user=> (class ::derp) clojure.lang.Keyword user=>
![Page 18: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/18.jpg)
def binds namesuser=> pi ;; NOOOOO!! ⇒ Undefined.CompilerException java.lang.RuntimeException: ...
user=> (def pi 3.1415926)#'user/pi
user=> pi3.1415926
user=> (println pi) 3.1415926nil
![Page 19: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/19.jpg)
Data Structures
● Lists - singly-linked, front-append○ (1 2 3 4)
● Vectors - indexed, back-append○ [:a 2 3 “4”]
● Maps - key/value store○ {:a 2 :b 4}
● Sets○ #{:a :b :c :d}
![Page 20: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/20.jpg)
Expressions are Data
From: http://alandipert.github.io/oscon2012-clojure/
![Page 21: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/21.jpg)
Expressions are Data
vs…
From: http://alandipert.github.io/oscon2012-clojure/
![Page 22: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/22.jpg)
Expressions are Data
(op ...)● op can be a ….
○ Function: +, mod, println○ Macro: when, cond, and○ Special Operator: do, if, ref○ Higher-order function○ … anything callable (clojure.lang.IFn)
![Page 23: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/23.jpg)
Function calls use parens...user=> (defn hello [] "Hi!!!") ;; define hello functionuser=> hello ;; return it#<user$hello user$hello@be1a6e>user=> (hello) ;; invoke it"Hi!!!"
… but values never douser=> (def my-name "Kelly Q. Programmer") #'user/my-name user=> my-name"Kelly Q. Programmer"user=>(my-name)ClassCastException java.lang.String cannot be cast to clojure.lang.IFn
![Page 24: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/24.jpg)
Quote makes “variables” symbolicuser=> (def x 3)#'user/x
user=> (+ x 2)5
user=> '(+ x 2) ;; quoted list(+ x 2) ;; returns list, unevaluated
user=> (quote (+ x 2)) ;; same as above(+ x 2)
![Page 25: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/25.jpg)
Introspect your Environmentsuser=> (use 'clojure.repl) ;; Quoted symbol user=> (doc if) ;; Print docstring------------------------- if (if test then else?)Special Form Evaluates test. If not the singular values nil or false, evaluates and yields then, otherwise, evaluates and yields else. If else is not supplied it defaults to nil.
Please see http://clojure.org/special_forms#ifnil
![Page 26: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/26.jpg)
Introspect your Environmentsuser=> (source when) (defmacro when "Evaluates test. If logical true, evaluates body in an implicit do." {:added "1.0"} [test & body] (list 'if test (cons 'do body)))nil
For More:● find-doc - Print docstring for var whose doc or name matches a pattern
● apropos - returns a seq of definitions matching a regex
● pst - print stack trace for a given exception or *e by default
● See: http://clojure.org/cheatsheet
![Page 27: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/27.jpg)
Namespaces are all around you
● Namespaces disambiguate names○ vars -> symbols, functions, macros, Java class etc.
are all defined in namespaces● Namespace management is a big part of
Clojure development(ns com.your.great.app (:require clojure.string [clojure.set :as set] [clojure.java.io :refer (file reader)]))
![Page 28: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/28.jpg)
Functions
![Page 29: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/29.jpg)
Functional Abstractions are Useful
● Clojure is functional● Functions and higher-order functions are
generic in a obviously fundamental ways● clojure.core (mostly) free of side-effects● TBDL: Immutability and persistence
guarantee behavior and performance
![Page 30: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/30.jpg)
defn binds functions(defn messenger ;; multi-arity definition ([] ;; no args (messenger "Hi!")) ;; call self with default ([msg] ;; one arg (println msg)) ;; print it ([msg & args] ;; variadic definition (println msg args))) ;; apply print to all argsuser=> (messenger)Hi!user=> (messenger "Hi class!")Hi class!user=> (messenger "Hi class!" "Who?" "What?")Hello class! (Who? What?)
![Page 31: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/31.jpg)
fn creates anonymous functions● fn creates lambdas (fn [message] (println message) )
( (fn [message] (println message) ) “Hi!”)Hi!nil
![Page 32: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/32.jpg)
apply applies functions
● Invokes argument on arguments (last is a sequence).
;; & puts rest of args into sequence;; apply pulls args out of sequence(defn messenger [greeting & who] (apply println greeting who))
user=> (messenger "Hi, everyone!" "Who?" "What?")Hi, everyone! Who? What?
![Page 33: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/33.jpg)
let binds symbols to values
● Values are either literal or expressions● Bound symbols have “lexical scope”(defn messenger [msg] (let [a “Who?” b “What?” c (capitalize msg)] (println a b c)))
user=> (messenger “Why?”)
Who? What? Why?
![Page 34: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/34.jpg)
Closures
● Allows bindings to persist beyond the lexical scope
(defn messenger-builder [greeting] (fn [who] (println greeting who))) ;; defines closure
;; greeting provided here, then goes out of scope(def hello-er (messenger-builder "Hello"))
;; greeting still available because hello-er is closureuser=> (hello-er "world!")Hello world!
![Page 35: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/35.jpg)
Flow Control
![Page 36: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/36.jpg)
Expressions in Clojure
● Java, etc. : Expressions return values, but statements do not.
String s;
if (s == “foo”) {
s = “bar”;
}
return s;
● Clojure: Everything is an expression (-> value or nil)
(if (= s “foo”) “bar”)
(do (stuff) ;; Do stuff.
(= s “foo”) ;; => true
![Page 37: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/37.jpg)
Flow Control Operators
● if, when, if-not, when-not, do, cond, case, etc. are all flow control operators.
● composable and general
![Page 38: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/38.jpg)
“Truthiness”(if true :truthy :falsey) ;;=> :truthy, and so are:(if (Object.) :truthy :falsey) ;; objects(if [] :truthy :falsey) ;; empty collections(if 0 :truthy :falsey) ;; zero
(if false :truthy :falsey) ;;=> :falsey(if nil :truthy :falsey) ;; nil(if (seq []) :truthy :falsey) ;; seq on empty collection
(and true 0 22) ;; returns last expression
(or true false 22)
![Page 39: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/39.jpg)
if, do, and whenuser => (if (even? 5) ;; if is multibranch (do (println "Even!") ;; do evaluates block and true) ;; returns last value (do (println "Odd!") false))odd ;; printedfalse ;; return value
user => (when (even? 5) ;; when is single-branch (println "Even!") ;; sugar for (if <>(do..)) true)
![Page 40: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/40.jpg)
cond and case(let [x 22] ;; Compares predicates (cond (<= x 22) "Dismissed as coincidence." (> x 222) "x is greater than 222." :else "No conditions met"))
(defn bazbar [x] ;; Matches arguments (case x ;; in O(1) time 22 "x is 22" ;; Must be literals 222 "x is 222" "x is neither 22 or 222"))
![Page 41: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/41.jpg)
Iterations (and side effects)(dotimes [i 5] ;; Evals and returns nil. (println i))
(doseq [letter [:a :b :c] ;; Imperative cartesian product. number (range 5)] (println [letter number]))
(for [letter [:a :b :c] ;; Sequence cartesian product. number (range 5)] [letter number]) ;; ([:a 0] [:a 1] [:a 2] [:b 0] ;; [:b 1] [:b 2] …)
![Page 42: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/42.jpg)
Threading Macros Remove Nesting ;; Deeply-nested parens ...
(first (.split (.replace (.toUpperCase "a b c d") "A" "X")
" "))
;; ... are unwinded with thread-first macro
(-> "a b c d"
.toUpperCase
(.replace "A" "X")
(.split " ")
first)
;; Also ->>, as->, cond->, cond->>, etc.
![Page 43: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/43.jpg)
Recursion (with loop/recur)
● loop binds, recur re-loops ● Strong prefer iteration and higher-order
functions over recursion
(loop [i 0] (if (< i 22) (recur (inc i)) i))
22
![Page 44: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/44.jpg)
Today ….● Intro to Clojure● Clojure Overview & REPL● Functions● Flow Control● Collections● Sequences
![Page 45: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/45.jpg)
Collections
● Extensive facilities for representing and manipulating data
● Small number of data structures● Seq abstraction common across data
structures● Large library of functions across all of them
![Page 46: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/46.jpg)
Collections: Immutability
● Simple (numbers, strings) and compound values are immutable
● Key to Clojure's concurrency model● Cannot change immutable values
○ Generate new ones instead○ Persistent data structures for efficiency
![Page 47: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/47.jpg)
Collections: Persistent Data Structures● New values = old values + modifications● New values are not full copies● New value and old value are both available
after 'changes'● Performance guarantees for most operations● All Clojure data structures are persistent
![Page 48: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/48.jpg)
Collections: Persistent Data Structures
http://eclipsesource.com/blogs/2009/12/13/persistent-trees-in-git-clojure-and-couchdb-data-structure-convergence/
![Page 49: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/49.jpg)
Collections: Data Structures
● Sequential: list
![Page 50: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/50.jpg)
Collections: Data Structures
● Sequential: list○ Singly-linked lists○ Prepend: O(1)○ Lookup: O(1) at head, O(n) anywhere else○ Grow at the head (front)
![Page 51: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/51.jpg)
Collections: Data Structures
● Sequential: list() ;=> the empty list
(:a :b :c) ; error because :a not function
'(:a :b :c) ;=> (:a :b :c)
(list :a :b :c) ;=> (:a :b :c)
(conj '(:b :c) :a) ;=> (:a :b :c)
![Page 52: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/52.jpg)
Collections: Data Structures
● Sequential: list, vector
![Page 53: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/53.jpg)
Collections: Data Structures
● Sequential: list, vector○ Indexed, random-access, array-like○ Append: O(1) *○ Lookup: O(1) *○ Grow at the tail (end)
O(1) * = O(log 32 n), really close to O(1),is O(1) for n < 1 billion
![Page 54: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/54.jpg)
Collections: Data Structures
● Sequential: list, vector[] ;=> the empty vector[:a :b :c] ;=> [:a :b :c](vector :a :b :c) ;=> [:a :b :c](vec '(:a :b :c)) ;=> [:a :b :c]
(nth [:a :b :c] 0) ;=> :a
(conj [:a :b] :c) ;=> [:a :b :c]
![Page 55: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/55.jpg)
Collections: Data Structures
● Sequential: list, vector● Associative: map
![Page 56: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/56.jpg)
Collections: Data Structures
● Sequential: list, vector● Associative: map
○ Key → value, hash table, dictionary○ Insert and lookup: O(1) *○ Unordered
![Page 57: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/57.jpg)
Collections: Data Structures
● Sequential: list, vector● Associative: map
{} ;;=> the empty map{:a "a" :b "b"} ;;=> {:a "a" :b "b"}
(get {:a "a"} :a) ;;=> "a"(get {:a "a"} :z) ;;=> nil ; not found(get {:a "a"} :z 22) ;;=> 22 ; default
(assoc {:a "a"} :b "b") ;;=> {:a "a" :b "b"}(dissoc {:a "a"} :a) ;;=> {}(conj {} [:a "a"]) ;;=> {:a "a"}
![Page 58: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/58.jpg)
Collections: Data Structures
● Sequential: list, vector● Associative: map
○ Nested access: get-in, assoc-in, update-in(def our-class {:class "Better Living Through Clojure" :location {:room "4-231"})
![Page 59: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/59.jpg)
Collections: Data Structures
● Sequential: list, vector● Associative: map
○ Nested access: get-in, assoc-in, update-in(def our-class {:class "Better Living Through Clojure" :location {:room "4-231"})(get (get our-class :location) :room) ;;=> "4-231"
![Page 60: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/60.jpg)
Collections: Data Structures
● Sequential: list, vector● Associative: map
○ Nested access: get-in, assoc-in, update-in(def our-class {:class "Better Living Through Clojure" :location {:room "4-231"})(get (get our-class :location) :room) ;;=> "4-231"(-> our-class (get :location) (get :room)) ;;=> "4-231"
![Page 61: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/61.jpg)
Collections: Data Structures
● Sequential: list, vector● Associative: map
○ Nested access: get-in, assoc-in, update-in(def our-class {:class "Better Living Through Clojure" :location {:room "4-231"})(get (get our-class :location) :room) ;;=> "4-231"(-> our-class (get :location) (get :room)) ;;=> "4-231"(get-in our-class [:location :room]) ;;=> "4-231"
![Page 62: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/62.jpg)
Collections: Data Structures
● Sequential: list, vector● Associative: map, set
![Page 63: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/63.jpg)
Collections: Data Structures
● Sequential: list, vector● Associative: map, set
○ Set of distinct values○ Insert: O(1) *○ Member?: O(1) *○ Unordered
![Page 64: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/64.jpg)
Collections: Data Structures
● Sequential: list, vector● Associative: map, set
#{} ;;=> the empty set#{"a" "b"} ;;=> #{"a" "b"}
(set ["a" "b"]) ;;=> #{"a" "b"}
(conj #{} "a") ;;=> #{"a"}
(contains? #{"a"} "a") ;;=> true
![Page 65: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/65.jpg)
Collections: Data Structures are Functions● Maps are functions of their keys
(def dict {:a "a" :b "b"})(dict :b) ;;=> "b"
![Page 66: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/66.jpg)
Collections: Data Structures are Functions● Maps are functions of their keys
(def dict {:a "a" :b "b"})(dict :b) ;;=> "b"
● Keywords are functions of maps(:b dict) ;;=> "b"
![Page 67: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/67.jpg)
Collections: Data Structures are Functions● Maps are functions of their keys
(def dict {:a "a" :b "b"})(dict :b) ;;=> "b"
● Keywords are functions of maps(:b dict) ;;=> "b"
● Sets are functions of their elements(def s #{3 7 9})(s 7) ;;=> 7
![Page 68: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/68.jpg)
Collections: Data Structures are Functions● Maps are functions of their keys
(def dict {:a "a" :b "b"})(dict :b) ;;=> "b"
● Keywords are functions of maps(:b dict) ;;=> "b"
● Sets are functions of their elements(def s #{3 7 9})(s 7) ;;=> 7
● Vectors are functions of their indices(def v [:a :b :c])(v 1) ;;=> :b
![Page 69: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/69.jpg)
Collections: Destructuring● Declarative way to pull apart compound data
○ vs. explicit, verbose access● Sequential & associative data structures● Nests for deep, arbitrary access● Works in fn and defn params, let bindings
![Page 70: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/70.jpg)
Collections: Destructuring;; Without destructuring:(defn next-fib-pair [pair] [(second pair) (+ (first pair) (second pair))])
![Page 71: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/71.jpg)
Collections: Destructuring;; Without destructuring:(defn next-fib-pair [pair] [(second pair) (+ (first pair) (second pair))])
;; With destructuring:(defn next-fib-pair [[x y]] [y (+ x y)])
![Page 72: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/72.jpg)
Today ….● Intro to Clojure● Clojure Overview & REPL● Functions● Flow Control● Names & Namespaces● Collections● Sequences
![Page 73: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/73.jpg)
Sequences
● Abstraction for representing iteration● Backed by a data structure or a function
○ Can be lazy and/or "infinite"● Foundation for large library of functions
![Page 74: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/74.jpg)
Sequences: API
● (seq coll)○ If collection is not empty, return seq object on it○ If collection is empty, return nil
![Page 75: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/75.jpg)
Sequences: API
● (seq coll)○ If collection is not empty, return seq object on it○ If collection is empty, return nil
● (first coll) returns the first element
![Page 76: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/76.jpg)
Sequences: API
● (seq coll)○ If collection is not empty, return seq object on it○ If collection is empty, return nil
● (first coll) returns the first element● (rest coll) returns a sequence of the rest of
the elements
![Page 77: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/77.jpg)
Sequences: API
● (seq coll)○ If collection is not empty, return seq object on it○ If collection is empty, return nil
● (first coll) returns the first element● (rest coll) returns a sequence of the rest of
the elements● (cons x coll) returns a new sequence: first is
x, rest is coll
![Page 78: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/78.jpg)
Sequences: Example(seq [1 2 3]) ;=> (1 2 3) ; not a list
(seq "Clojure") ;=> (\C \l \o \j \u \r \e)
(seq {:a 1 :b 2}) ;=> ([:a 1] [:b 2]) ; seq of map entries
(seq a-java-array) ;=> (...)
(seq []) ;=> nil(seq "") ;=> nil(seq {}) ;=> nil
![Page 79: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/79.jpg)
Sequences: Over Structures
● We can treat any data structure as a seq
1 2 3
s
(def s '(1 2 3)) ; s is a list
![Page 80: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/80.jpg)
Sequences: Over Structures
● We can treat any data structure as a seq(def s '(1 2 3)) ; s is a list
1 2 3
s
a
(def a (first s)) ; a is 1
![Page 81: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/81.jpg)
Sequences: Over Structures
● We can treat any data structure as a seq(def s '(1 2 3)) ; s is a list(def r (rest s)) ; r is a seq
1 2 3
s r
![Page 82: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/82.jpg)
Sequences: Over Structures
● We can treat any data structure as a seq(def s '(1 2 3)) ; s is a list(def b (first (rest s)) ; b is 2(def b (second s)) ; same thing
1 2 3
s
b
![Page 83: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/83.jpg)
Sequences: Over Structures
● We can treat any data structure as a seq○ Lists are seqs○ Others are wrapped○ Associative structures become sequence of pairs
![Page 84: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/84.jpg)
Sequences: Over Functions
● Can map a generator function to a seq● Seq is lazy, can be infinite
● Can process more than fits in memory(def r (range 1 100)) ; r is a lazy seq(def a (first r)) ; a is 1(def s (rest r)) ; s is a lazy seq(def b (first (rest r)) ; b is 2(def b (second r)) ; same thing(def c (first (rest (rest r)))) ; c is 3(def c (nth r 2)) ; same thing
![Page 85: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/85.jpg)
Sequences: Generation(range) ;=> (0 1 2 ... infinite
(range 5) ;=> (0 1 2 3 4)
(repeat :b) ;=> (:b :b :b ... infinite
(repeatedly #(rand-int 100)) ;=> (89 58 73 ... infinite
![Page 86: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/86.jpg)
Sequences: Into Collections(into #{} "hello") ;=> #{\e \h \l \o}
(into {} [[:x 1] [:y 2]]) ;=> {:x 1, :y 2}
(into () [:a :b :c]) ;=> (:c :b :a)
![Page 87: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/87.jpg)
Sequences: Shorten(take 3 (range)) ;=> (0 1 2)
(drop 3 (range)) ;=> (3 4 5 ... infinite
(filter even? (range)) ;=> (0 2 4 6 ... infinite
(remove even? (range)) ;=> (1 3 5 7 ... infinite
![Page 88: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/88.jpg)
Sequences: Lengthen(concat [:a :b] (range 2 5)) ;=> (:a :b 2 3 4)
(cycle [:a :b :c]) ;=> (:a :b :c :a :b ... infinite
(interpose \, (range 3)) ;=> (0 \, 1 \, 2)
![Page 89: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/89.jpg)
Sequences: map(map even? (range 1 5)) ;=> (false true false true)
(map + [1 2 3] [4 5 6]) ;=> (5 7 9)
(map * [1 2 3] (range 1000)) ;=> (0 2 6)
![Page 90: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/90.jpg)
Sequences: reduce(reduce function init seq)
● function takes 2 arguments: accumulator and the current argument● reduce calls (function init (first seq))● Return value becomes init for next step● Repeat until the end of the seq, returns the last init
(reduce (fn [total item] (+ total (* 10 item))) 0 ; init [1 2 3 4]) ;=> 100
![Page 91: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/91.jpg)
Sequences: some(some even? [1 2 3 4]) ;=> true
(some #{:foo} [:baz :bar :foo]) ;=> :foo
![Page 92: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/92.jpg)
;; Sum of the first 50 odd integers(reduce + (take 50 (filter odd? (range)))) ;=> 2500
Combine sequence functions: Power
;; Top 5 most frequently used words in the docstrings of the current namespace(->> (ns-publics *ns*) (map (comp :doc meta val)) (remove nil?) (mapcat (fn [s] (re-seq #"\w+" s))) (frequencies) (sort-by val) (reverse) (take 5) (map first))
![Page 93: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/93.jpg)
In this Class● Testing● Concurrency● Polymorphism● JVM Interop● Performance● Tooling● Interesting Problems Solved by Clojure● Our Projects
![Page 94: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/94.jpg)
clojure.test(deftest math-basics (is (= 3 (+ 1 2))) (is (= 10 (* 2 5))) (is (thrown? java.lang.ArithmeticException (/ 1 0))))
![Page 95: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/95.jpg)
midje(fact (+ 1 2) => 3 (* 2 5) => 10 (/ 1 0) => (throws java.lang.ArithmeticException))
![Page 96: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/96.jpg)
expectations(expect 3 (+ 1 2))
(expect 10 (* 2 5))
(expect java.lang.ArithmeticException (/ 1 0))
![Page 97: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/97.jpg)
In this Class● Testing● Concurrency● Polymorphism● JVM Interop● Performance● Tooling● Interesting Problems Solved by Clojure● Our Projects
![Page 98: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/98.jpg)
Benefits of Immutability
● What is a race condition?
● How does immutability help?
![Page 99: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/99.jpg)
Atoms;; Create atom with initial value(def a (atom 0))
;; Atomically transition from old to new value(swap! a (fn [old-value] (+ 3 old-value)))
;; Set to a new value, regardless of old value(reset! a 22)
![Page 100: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/100.jpg)
Refs and Agents
● Refs allow you do many “swap!”s transactionally○ aka Software Transactional Memory
● Agents allow you do do “swap!”s asynchronously on a thread pool○ a dual of actors: send functions to the value, rather
than values (messages) to the function (actor)
![Page 101: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/101.jpg)
core.async
● Go-style communicating sequential processes
● “select” operator● Scalable user-space scheduling● Works in ClojureScript● See the talk from Clojure Conj here
![Page 102: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/102.jpg)
In this Class● Testing● Concurrency● Polymorphism● JVM Interop● Performance● Tooling● Interesting Problems Solved by Clojure● Our Projects
![Page 103: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/103.jpg)
Two kinds of polymorphism
Protocols Multimethods
Dispatch The first argument’s type Arbitrary function of all arguments
Performance Fast; uses native virtual dispatch Slow; requires a hash table lookup
Popularity Extremely popular, good reputation Used only when arbitrary dispatch is necessary
![Page 104: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/104.jpg)
Protocols
● Solves the expression problem○ “How can we extend existing functions to new
datatypes and new functions to existing datatypes without recompiling all code?”
● Uses perfect hashing and Java interfaces for dispatching
![Page 105: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/105.jpg)
Protocols - Example(defprotocol ITaskRunner (run [this task] "run the task, which is a fn"))(defrecord ThreadRunner [name] ITaskRunner (run [this task] (future (task)))(defrecord ImmediateRunner [nickname] ITaskRunner (run [this task] (task)))
(run (->ThreadRunner "Bob") (fn [] (println "hello world from thread")))(run (->ImmediateRunner "Lily") (fn [] (println "hello world from stack")))
![Page 106: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/106.jpg)
Protocols - Example(defprotocol INamed (named [this] "Return the name of this"))
(extend-protocol INamed TaskRunner (named [this] (:name this)) ImmediateRunner (named [this] (:nickname this)))
(named (->ThreadRunner "Bob"));;=> "Bob"(named (->ImmediateRunner "Lily"));;=> "Lily"
![Page 107: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/107.jpg)
Multimethods - Example;; We define a multimethod with its dispatch function(defmulti battle "Engage 2 spacecraft in epic battle" (fn [x y] [(:type x) (:type y)]))
;; We can even create hierarchies of keywords.;; Java types are permissible as leaves(derive :x-wing :ship)
![Page 108: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/108.jpg)
Multimethods - Example;; We can define arbitrary numbers of implementations(defmethod battle [:death-star :planet] [death-star planet] (str planet " has been obliterated by " death-star))(defmethod battle [:ship :star-destroyer] [ship destroyer] (str ship " has been eliminated by " destroyer "defenses"))
(defmethod battle [:x-wing :death-star] [x-wing death-star] (str x-wing " perfectly shot its proton torpedoes into " death-star))
![Page 109: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/109.jpg)
In this Class● Testing● Concurrency● Polymorphism● JVM Interop● Performance● Tooling● Interesting Problems Solved by Clojure● Our Projects
![Page 110: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/110.jpg)
Exceptions(try (do-something-that-could-fail) (catch RuntimeException e (print-stack-trace e)) (finally (dispose-of-resources)))
![Page 111: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/111.jpg)
Making your own Exceptions(try (throw (ex-info "A data-carrying exception" {:x 22 :y 42})) (catch clojure.lang.ExceptionInfo e (println ":x is" (:x (ex-data e)))))
![Page 112: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/112.jpg)
Java InteropTask Java Clojure
Instantiation new MyClass(“foo”) (MyClass. “foo”)
Instance method dog.bark() (.bark dog)
Instance field object.field (.-field object)
Static method Math.sin(22) (Math/sin 22)
Static field Math.PI Math/PI
![Page 113: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/113.jpg)
Java Methods vs. Clojure Functions;; Works(map str (range 10));; Doesn’t work(map .toString (range 10));;Works(map (fn [x] (.toString x)) (range 10))
![Page 114: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/114.jpg)
Clojure Types are Java TypesClojure Type Java Type
Long java.lang.Long
Double java.lang.Double
Boolean java.lang.Boolean
String java.lang.String
Regex java.util.regex.Pattern
BigDecimal java.lang.BigDecimal
BigInt clojure.lang.BigInt (wraps java.lang.BigInteger or long)
![Page 115: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/115.jpg)
Clojure Types are Java TypesClojure Type Java Type
Function java.lang.Runnable, java.util.concurrent.Callable
List java.util.List *
Vector java.util.List *
Map java.util.Map *
Set java.util.Set *
* Does not include mutation operators, like add() or put()
![Page 116: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/116.jpg)
In this Class● Testing● Concurrency● Polymorphism● JVM Interop● Performance● Tooling● Interesting Problems Solved by Clojure● Our Projects
![Page 117: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/117.jpg)
How long did it take?;;Built-in (simple)(time (dotimes [i 1000] (+ 1 1)))
;;Criterium (statistically robust)(criterium.core/bench (+ 1 1))
![Page 118: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/118.jpg)
Clojurians care about Speed
● Transient collections● Protocols● Unboxed numeric support in the compiler● no.dissassemble (inspect bytecode of fn)● Performance-oriented libraries
○ core.async - user space threading○ core.matrix - matrix math○ narrator - time series analysis
![Page 119: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/119.jpg)
What’s in your toolkit?Complex Simple
State, Objects, Methods Values, Functions/Namespaces
Variables Managed references and concurrency
Inheritance, switch, matching Polymorphism
Syntax Data
Imperative loops, folds Sequence Functions
Conditionals Rules
Inconsistency Consistency and Design
“Paradigms” Syntactic Abstraction
![Page 120: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/120.jpg)
In this Class● Testing● Concurrency● Polymorphism● JVM Interop● Performance● Tooling● Interesting Problems Solved by Clojure● Our Projects
![Page 121: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/121.jpg)
Leiningen● “for automating Clojure projects without setting your hair on fire”● Functional project management● Fetches dependencies and constructs classpath● Packages and deploys project● Easily extensible with plugins
![Page 122: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/122.jpg)
Leingen - usage
lein new my-cool-project
lein repl
lein uberjar
lein deploy clojars(defproject my-cool-project "0.1.0-SNAPSHOT" ... :dependencies [[org.clojure/clojure "1.4.0"] [ring "1.2.1"]])
![Page 123: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/123.jpg)
Vim
● fireplace○ Simple evaluation○ Prefix intellisense○ Documentation lookup○ Go to source
● redl○ Advanced REPL with simple debugger○ Fuzzy intellisense
![Page 124: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/124.jpg)
Emacs
● cider○ Advanced REPL○ Documentation lookup○ Symbol completion○ Source lookup
● ritz○ Stepping debugger via JVM’s debugging API○ All features of cider
![Page 125: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/125.jpg)
Light Table
● Easiest to get started● REPL● Inline documentation● Written in Clojure(Script)!
![Page 126: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/126.jpg)
Paredit + Rainbow Parens
● It’s really hard to keep parens, braces, and brackets matching
● It’s really hard to see which ones are pairs● Let your editor handle it!
![Page 127: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/127.jpg)
In this Class● Testing● Concurrency● Polymorphism● JVM Interop● Performance● Tooling● Interesting Problems Solved by Clojure● Our Projects
![Page 128: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/128.jpg)
Clojure Toolbox
● clojure-toolbox.com● Great starting point for projects!● Database clients, web frameworks, data
structures, parsers, etc.
![Page 129: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/129.jpg)
● Purely functional database
● Horizontal read scalability
![Page 130: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/130.jpg)
Storm
● Hadoop for real-time data
● Used by Twitter to process all tweets in real-time (and by many others!)
![Page 131: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/131.jpg)
Riemann
● Event processor and monitoring tool for distributed systems
● Makes it easy to monitor clusters, calculate statistics, and send alerts
![Page 132: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/132.jpg)
Instaparse
What if context-free grammars were as easy to use as regular expressions?
(insta/parser "S = AB* AB = A B A = 'a'+ B = 'b'+")
![Page 133: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/133.jpg)
In this Class● Testing● Concurrency● Polymorphism● JVM Interop● Performance● Tooling● Interesting Problems Solved by Clojure● Our Projects
![Page 134: Clojure class](https://reader034.vdocuments.site/reader034/viewer/2022050808/54c677014a7959d3298b45b7/html5/thumbnails/134.jpg)
Sources
● http://clojure.org● Talks by Rich Hickey: Clojure, Are We There
Yet, and Simple Made Easy● Beating the Averages, Paul Graham