Clojure Lisp for the Real World @stuartsierra #clojure 1
Bullet Points Values Code is data Generic data access Concurrency 2
Stuart Sierra Relevance, Inc. Clojure/core Clojure contributor 3
Values 4
Values 3 5
Values 3 + 2 = 5 6
Values let x = 3 7
Values let x = 3 let x = 5 8
Values let 3 = 5 9
Values define 3 = 5 10
Values 3 11
Values Immutable 3 12
Values Immutable 3 Persistent 13
" He llo, world! " 14
char greeting[14]; strcpy(greeting, "Hello, World!"); greeting H e l l o, w o r l d! \0 15
char* name = greeting + 7; greeting name H e l l o, w o r l d! \0 16
name[7] = 'b'; name[10] = 'e'; greeting name H e l l o, b o r e d! \0 17
String greeting = new String("Hello, world!"); greeting java.lang.string H e l l o, w o r l d! 18
String alt = greeting.replace("world", "bored"); greeting java.lang.string H e l l o, w o r l d! alt java.lang.string H e l l o, b o r e d! 19
greeting java.lang.string H e l l o, w o r l d! Immutable 20
In the real world, values don't change. 21
Clojure Values 3 Long 6.022e23 Double "Hello, world!" String 3.0M BigDecimal 9223372036854775808N BigInt 2/3 Ratio 22
Clojure Values even? :last-name (print 99 "bottles") Symbol Keyword List [3.14 :pi] Vector {:x 3 "y" 4} Map #{7 9 "foo"} Set 23
Clojure Values Immutable Persistent 24
String alt = greeting.replace("world", "bored"); greeting java.lang.string H e l l o, w o r l d! alt java.lang.string H e l l o, b o r e d! 25
Clojure Values List O(1) at the head O(n) anywhere else Vector O(log32n) access Map O(log32n) access Set O(log32n) contains? 26
............ 27
32 1 = 32 32 2 = 1024 32 3 = 32,768 32 4 = 1,048,576 32 5 = 33,554,432 32 6 = 1,073,741,824 32 7 = 34,359,738,368 28
log32 1000 < 2 log32 10,000 < 3 log32 1,000,000 < 4 log32 10,000,000 < 5 log32 1,000,000,000 < 6 29
In the real world, log32n is fast enough. 30
Code is Data 31
Code is Data #{ {:first "Stuart" :last "Sierra"} {:first "Luke" :last "VanderHart"} {:first "Michael" :last "Fogus"} } 32
Code is Data #{ {:first "Stuart" :last "Sierra"} {:first "Luke" :last "VanderHart"} {:first "Michael" :last "Fogus"} } A set of maps 33
Symbol List (+ 3 4 5) 34
Symbol List (+ 3 4 5) Function call 35
Symbols Symbols List Vector Function call (defn average [& nums] (/ (reduce + nums) (count nums))) (average 3 4 5) 36
Host Interop. constructor (def m (ConcurrentHashMap. 100)) (.put m "key" "value") method call 37
You Characters Lexer/Parser Abstract Syntax Tree Compiler/ Interpreter 38
You Characters Clojure Reader Data Structures Clojure Compiler 39
You Characters Clojure Reader Macros Data Structures Clojure Compiler 40
(let [file...initializer...] (try... do something... (finally (.close file)))) 41
(defmacro with-open [bindings & body] `(let ~bindings (try ~@body (finally (.close ~(first bindings))))) 42
(let [file...initializer...] (try... do something... (finally (.close file)))) 43
(with-open [file...initializer...]... do something...) 44
Generic data access 45
Generic data access #{ {:first "Stuart" :last "Sierra"} {:first "Luke" :last "VanderHart"} {:first "Michael" :last "Fogus"} } A set of maps 46
Author[] authors =... String names[] = new names[authors.length]; for (int i = 0; i < authors.length; i++) { names[i] = authors[i].getfirstname(); } 47
(defn get-first-name [author] (get author :first)) (map get-first-name authors) ("Stuart" "Luke" "Michael") Higher-order function 48
Anonymous function (map (fn [a] (get a :first)) authors) ("Stuart" "Luke" "Michael") 49
Anonymous function (map #(get % :first) authors) ("Stuart" "Luke" "Michael") 50
Maps are functions (map #(% :first) authors) ("Stuart" "Luke" "Michael") 51
Keywords are functions! (map #(:first %) authors) ("Stuart" "Luke" "Michael") 52
Keywords are functions (map :first authors) ("Stuart" "Luke" "Michael") 53
String names[] = new names[authors.length]; for (int i = 0; i < authors.length; i++) { names[i] = authors[i].getname(); } vs. (map :first authors) 54
(map function set-of-maps) 55
(map function map-of-maps) (map function list-of-vectors) (map function vector-of-sets-of-maps) (map function set-of-maps) 56
(map function map-of-maps) (map function list-of-vectors) (map function vector-of-sets-of-maps) (map function set-of-maps) (map function (file-seq directory)) (map function (line-seq file)) (map function (xml-seq xml-tree)) (map function (resultset-seq query)) 57
Sequence API Sequence Generators map filter reduce count some remove replace and lots more... List Vector Map ResultSet Stream Directory Iterator XML and lots more... 58
Polymorphism 59
Object-Oriented, The Good Parts 60
dispatch function method method multimethod method method method 61
method protocol method method method Protocol method protocol method method method 62
Existing Interfaces Your new protocol here Existing Types Existing Method Implementations Your new type here and here! 63
The Expression Problem Sierra "Solving the Expression Problem with Clojure 1.2" IBM DeveloperWorks Chris Houser "Clojure's Solutions to the Expression Problem" Strange Loop 2010 64
Concurrency 65
Parallelism Concurrency State 66
class Invoice { private Date date; public Date getdate() { } return this.date; } public void setdate(date date) { } this.date = date; 67
class Date { public void setday(int day); public void setmonth(int month); public void setyear(int year); } Mutable! 68
class Invoice { private Date date; public Date getdate() { } return this.date; public void setdate(date date) { this.date = date; } } Better not change it! 69
class Invoice { private Date date; public Date getdate() { return this.date; Better not change it! } public void setdate(date date) { } this.date = date; } Better not change it! 70
Programming with immutable values means never having to say you're sorry. 71
today July 25 72
today July 25 July 26 73
Identity today State July 25 Value July 26 Value 74
Identity today State July 25 function July 26 Value Value 75
Identity today State July 24 function July 25 function July 26 Past Present Future 76
Identity today State July 24 function July 25 function July 26 Past Present Future The future is a function of the past. 77
Mutable References Ref Atom Var Agent 78
readers writer Atom writer retry abort 79
Atom (def tick (atom 1)) 1 (deref tick) 1 tick 80
Atom (def tick (atom 1)) (deref tick) 1 (swap! tick inc) @tick 2 tick 1 inc 2 81
Atom (def tick (atom 1)) (deref tick) 1 (swap! tick inc) @tick 2 (swap! tick + 10) @tick 12 tick 2 + 10 12 82
value value value value identity value value value value identity identity value value value value 83
value value value value identity value value value value identity identity value value value value 84
readers Ref writer writer transaction retry abort Ref 85
Ref (def A (ref 1)) (def B (ref 10)) A 1 B 10 86
Ref (def A (ref 1)) (def B (ref 10)) (dosync (alter A inc) (alter B + 10)) A 1 B 10 + 10 20 inc 2 transaction 87
Ref (def A (ref 1)) (def B (ref 10)) (dosync (alter A inc) (alter B + 10)) @A 2 @B 20 A B 20 2 88
Database Transactions Atomic Consistent Isolated Durable 89
Clojure Transactions Atomic Consistent Isolated 90
readers action queue action action Agent Agent Thread Pool 91
Agent (def A (agent 1)) queue A 1 92
Agent (def A (agent 1)) (send A inc) @A 1 queue inc A 1 93
Agent (def A (agent 1)) (send A inc) @A 1 queue A 1 inc @A 2 2 94
other threads Var root binding binding threadlocal threadlocal binding 95
Concurrency Ref Atom Var Agent 96
In the real world, JavaScript is everywhere 97
ClojureScript 98
More Clojure: clojure.org Clojure/core: clojure.com Me: stuartsierra.com @stuartsierra Image Credits openclipart.org pdtextures.blogspot.com Clojure logo by Tom Hickey 99