Slide 1

Slide 1 text

Clojure: Your New Favorite Language Howard M. Lewis Ship
 [email protected] @hlship

Slide 2

Slide 2 text

“A language that doesn't affect the way you think about programming is not worth knowing.” ! – Alan Perlis
 First recipient of the Turing Award

Slide 3

Slide 3 text

Power Focus Simplicity

Slide 4

Slide 4 text

“In mathematics, a function is a relation between a set of inputs and a set of permissible outputs with the property that each input is related to exactly one output.”

Slide 5

Slide 5 text

First Name String Last Name String SSN String Donate to Campaign Boolean

Slide 6

Slide 6 text

public class TaxPayer { private String firstName, lastName, SSN; ! private boolean donate = false; ! public String getFirstName() { return firstName; } ! public void setFirstName(String firstName) { this.firstName = firstName; } ! public String getLastName() { return lastName; } ! public void setLastName(String lastName) { this.lastName = lastName; … } Noun Verb Verb Verb Verb

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

manny.triggerConversation(0);

Slide 9

Slide 9 text

(def tax-payer {
 :first-name "Howard" :last-name "Lewis Ship" :ssn "…" :donate true })

Slide 10

Slide 10 text

O.M.G.  Lisp!

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

(def tax-payer {
 :first-name "Howard" :last-name "Lewis Ship" :ssn "…" :donate true }) (assoc tax-payer :tax-schedule "C")
 ➠ {:first-name "Howard"
 :last-name "Lewis Ship"
 :ssn "…"
 :donate true
 :tax-schedule "C"
 } Generic Verb

Slide 13

Slide 13 text

“It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures.”
 
 — Alan Perlis

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

“All non-trivial abstractions, to some degree, are leaky.” ! — Joel Spolsky

Slide 16

Slide 16 text

What makes Clojure different?

Slide 17

Slide 17 text

What makes Clojure better?

Slide 18

Slide 18 text

The full language … all the time

Slide 19

Slide 19 text

javac java
 (JVM) Java source .class

Slide 20

Slide 20 text

(…) Read Eval Print Loop
 REPL Clojure 
 Source

Slide 21

Slide 21 text

Clojure Basics

Slide 22

Slide 22 text

Test In Production Proper Integration Testing Unit Testing REPL

Slide 23

Slide 23 text

Pop Quiz Can any of these parenthesis be removed? if ((user != null && ((user.perms & WRITE_PERM) != 0)) || (record.version == snapshot.version)) { … } Don't Know / Don't Care

Slide 24

Slide 24 text

if ((user != null && ((user.perms & WRITE_PERM) != 0)) || (record.version == snapshot.version)) { … } (if (or (and user (-> user :perms (bit-and WRITE_PERM) pos?) (= (:version record) (:version snapshot))) … )

Slide 25

Slide 25 text

“Has anybody noticed that as languages grow in complexity, the best programmers switch to simpler languages?”
 —“Uncle” Bob Martin

Slide 26

Slide 26 text

Solving Problems in Clojure

Slide 27

Slide 27 text

Call a function Define a function Define and pass a function How do I do ______ in Clojure?

Slide 28

Slide 28 text

(defn largest [p1 p2] (if (> p1 p2) p1 p2)) symbol vector of parameters

Slide 29

Slide 29 text

Boring!

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

“Fifteen for two” “A run for four”

Slide 33

Slide 33 text

“A long double run for ten” “A run of four” “A different run of four” “A pair for two” “Fifteen for two”

Slide 34

Slide 34 text

Five or Four Card Flush Fifteens Pairs Runs of three, four, five Right Jack — “His Knees”

Slide 35

Slide 35 text

public enum Suit { SPADES, HEARTS, DIAMONDS, CLUBS }

Slide 36

Slide 36 text

public enum Rank { ACE(1), TWO(2), THREE(3),
 … JACK(10), QUEEN(10), KING(10); ! public final int points; ! Rank(int points) { this.points = points; } }

Slide 37

Slide 37 text

public class Card { public final Suit suit; ! public final Rank rank; ! public Card(Suit suit, Rank rank) { this.suit = suit; this.rank = rank; } ! @Override public String toString() { return String.format("%s of %s", StringUtils.capitalize(rank.name().toLowerCase()), StringUtils.capitalize(suit.name().toLowerCase())); } }

Slide 38

Slide 38 text

Clojure

Slide 39

Slide 39 text

{ :rank :ace :suit :spades }

Slide 40

Slide 40 text

(defn points [rank] (case rank :ace 1 :jack 10 :queen 10 :king 10 rank))

Slide 41

Slide 41 text

points ) ( ( ) :rank flip-card

Slide 42

Slide 42 text

points ) ( ( ) :rank flip-card

Slide 43

Slide 43 text

points :rank flip-card (-> ) ) ( ( ) flipCard.getRank().getPoints() vs.

Slide 44

Slide 44 text

No content

Slide 45

Slide 45 text

Scoring — Java

Slide 46

Slide 46 text

public interface Scorer { void score(List hand, List scores); } ! public class Score { public final int points; ! public final String description; ! public final Set cards = new HashSet<>(); ! public Score(int points, String description) { this.points = points; this.description = description; } ! public Score(int points, String description, Collection cards) { this(points, description); ! this.cards.addAll(cards); } }

Slide 47

Slide 47 text

public class FlushScorer implements Scorer { @Override public void score(List hand, List scores) { Suit flipSuit = hand.get(0).suit; ! boolean fiveFlush = true; ! for (int i = 1; i < 5; i++) { if (hand.get(i).suit != flipSuit) { fiveFlush = false; break; } } ! if (fiveFlush) { scores.add(new Score(5, "five card flush", hand)); ! return; } ! Suit firstSuit = hand.get(1).suit; ! for (int i = 2; i < 5; i++) { if (hand.get(i).suit != firstSuit) { return; } } ! scores.add(new Score(4, "four card flush", hand.subList(1, 5))); } }

Slide 48

Slide 48 text

(defn flush? "Returns true if the set of cards all have the same suit." [hand] (let [suits (map :suit hand) first-suit (first suits)] (every? #(= first-suit %) (rest suits)))) !

Slide 49

Slide 49 text

(defn flush? "Returns true if the set of cards all have the same suit." [hand] (let [suits (map :suit hand) first-suit (first suits)] (every? #(= first-suit %) (rest suits)))) !

Slide 50

Slide 50 text

(defn flush? "Returns true if the set of cards all have the same suit." [hand] (let [suits (map :suit hand) first-suit (first suits)] (every? #(= first-suit %) (rest suits)))) !

Slide 51

Slide 51 text

(map inc [3 4 5]) (4 5 6) ➠ (list (inc 3) (inc 4) (inc 5))

Slide 52

Slide 52 text

[{:suit :spades :rank 3} {:suit :hearts :rank 4} {:suit :hearts :rank 9} {:suit :hearts :rank 10} {:suit :hearts :rank :queen}] (:spades :hearts :hearts :hearts :hearts) (map :suit hand)

Slide 53

Slide 53 text

(defn flush? "Returns true if the set of cards all have the same suit." [hand] (let [suits (map :suit hand) first-suit (first suits)] (every? #(= first-suit %) (rest suits)))) !

Slide 54

Slide 54 text

Clojure seqs first - first element in collection rest - remaining elements in collection next - remaining elements or nil • java.util.Collection • String • Java primitive array • java.util.Map

Slide 55

Slide 55 text

(defn flush? "Returns true if the set of cards all have the same suit." [hand] (let [suits (map :suit hand) first-suit (first suits)] (every? #(= first-suit %) (rest suits)))) !

Slide 56

Slide 56 text

(defn flush? "Returns true if the set of cards all have the same suit." [hand] (let [suits (map :suit hand) first-suit (first suits)] (every? #(= first-suit %) (rest suits)))) !

Slide 57

Slide 57 text

No content

Slide 58

Slide 58 text

(defn score-flush "Returns a score map or nil depending on finding a four or five card flush." [hand] (cond (flush? hand) {:points 5 :text "five card flush" :cards hand} (flush? (rest hand)) {:points 4 :text "four card flush" :cards (rest hand)}))

Slide 59

Slide 59 text

(defn score "Constructs a score map." [points text cards] {:points points :text text :cards cards}) ! (defn score-flush "Returns a score map…" [hand] (cond (flush? hand) (score 5 "five card flush" hand) (flush? (rest hand)) (score 4 "four card flush" (rest hand))))

Slide 60

Slide 60 text

Scoring Pairs

Slide 61

Slide 61 text

public class PairsScorer implements Scorer { @Override public void score(List hand, List scores) { for (int i = 0; i < 4; i++) { Card left = hand.get(i); ! for (int j = i + 1; j < 5; j++) { Card right = hand.get(j); ! if (left.rank == right.rank) { Score score = new Score(2, "pair"); score.cards.add(left); score.cards.add(right); ! scores.add(score); } } } } } Match Cards Identify Pairs Score

Slide 62

Slide 62 text

Pop Quiz (rest [1 2 3])➠ ____ (rest '(2 3))➠ ____ (rest '(3))➠ ____ (rest ())➠ ____ (2 3) (3) () ()

Slide 63

Slide 63 text

(take 5 (iterate rest [1 2 3])) ([1 2 3] (2 3) (3) () ()) ➠

Slide 64

Slide 64 text

(defn score-pairs "Finds all pairs in the hand, returning a scoring map for each one." [hand] (for [sub-hand (take (-> hand count dec) (iterate rest hand)) :let [left (first sub-hand)] right (rest sub-hand) :when (= (:rank left) (:rank right))] (score 2 "a pair" [left right])))

Slide 65

Slide 65 text

(defn score-pairs "Finds all pairs in the hand, returning a scoring map for each one." [hand] (for [sub-hand (take (-> hand count dec) (iterate rest hand)) :let [left (first sub-hand)] right (rest sub-hand) :when (= (:rank left) (:rank right))] (score 2 "a pair" [left right])))

Slide 66

Slide 66 text

(for [suit [:hearts :diamonds :spades :clubs] rank [:ace 2 3 4 5 6 7 8 9 10 :jack :queen :king]] {:suit suit :rank rank}) ({:suit :hearts, :rank :ace} {:suit :hearts, :rank 2} … {:suit :clubs, :rank :queen} {:suit :clubs, :rank :king}) ➠

Slide 67

Slide 67 text

(defn score-pairs "Finds all pairs in the hand, returning a scoring map for each one." [hand] (for [sub-hand (take (-> hand count dec) (iterate rest hand)) :let [left (first sub-hand)] right (rest sub-hand) :when (= (:rank left) (:rank right))] (score 2 "a pair" [left right])))

Slide 68

Slide 68 text

(defn score-pairs "Finds all pairs in the hand, returning a scoring map for each one." [hand] (for [sub-hand (take (-> hand count dec) (iterate rest hand)) :let [left (first sub-hand)] right (rest sub-hand) :when (= (:rank left) (:rank right))] (score 2 "a pair" [left right])))

Slide 69

Slide 69 text

(defn score-pairs "Finds all pairs in the hand, returning a scoring map for each one." [hand] (for [sub-hand (take (-> hand count dec) (iterate rest hand)) :let [left (first sub-hand)] right (rest sub-hand) :when (= (:rank left) (:rank right))] (score 2 "a pair" [left right])))

Slide 70

Slide 70 text

(defn score-pairs "Finds all pairs in the hand, returning a scoring map for each one." [hand] (for [sub-hand (take (-> hand count dec) (iterate rest hand)) :let [left (first sub-hand)] right (rest sub-hand) :when (= (:rank left) (:rank right))] (score 2 "a pair" [left right])))

Slide 71

Slide 71 text

(defn score-pairs "Finds all pairs in the hand, returning a scoring map for each one." [hand] (for [sub-hand (take (-> hand count dec) (iterate rest hand)) :let [left (first sub-hand)] right (rest sub-hand) :when (= (:rank left) (:rank right))] (score 2 "a pair" [left right])))

Slide 72

Slide 72 text

(defn score-pairs "Finds all pairs in the hand, returning a scoring map for each one." [hand] (for [sub-hand (take (-> hand count dec) (iterate rest hand)) :let [left (first sub-hand)] right (rest sub-hand) :when (= (:rank left) (:rank right))] (score 2 "a pair" [left right]))) Match Cards Identify Pairs Score

Slide 73

Slide 73 text

No content

Slide 74

Slide 74 text

Extending Clojure in Clojure

Slide 75

Slide 75 text

No content

Slide 76

Slide 76 text

private final Lock lock = new ReentrantReadWriteLock(); ! public String getCachedValue() { try { lock.readLock().lock(); ! … } finally { lock.readLock().unlock(); } }

Slide 77

Slide 77 text

private final Lock lock = new ReentrantReadWriteLock(); ! public String getCachedValue() { withReadLock(lock) { … } }

Slide 78

Slide 78 text

Who owns the Java language?

Slide 79

Slide 79 text

Brian Goetz

Slide 80

Slide 80 text

Not You

Slide 81

Slide 81 text

Caution: Head Exploding Zone

Slide 82

Slide 82 text

Literals
 
 "Hello" 2.5 nil Vectors
 
 [ … ] Lists 
 '(1 2 3) Maps
 ! { … } Function Calls, Special Forms, Macros (a b c) Sets
 ! #{ … } Forms

Slide 83

Slide 83 text

Bytecode Generation Code Forms Macro Expansion def if let fn … .

Slide 84

Slide 84 text

(defn check-cache [key] (with-read-lock ) (read-from-cache! cache key) cache-lock )

Slide 85

Slide 85 text

(defn check-cache [key] ) (read-from-cache! cache key) (let [… ] (try … (finally …)) cache-lock )

Slide 86

Slide 86 text

(defmacro with-read-lock [lock & body] `(let [read-lock# (.readLock ~lock)] (try (.lock read-lock#) ~@body (finally (.unlock read-lock#)))))

Slide 87

Slide 87 text

(defmacro with-read-lock [lock & body] `(let [read-lock# (.readLock ~lock)] (try (.lock read-lock#) ~@body (finally (.unlock read-lock#)))))

Slide 88

Slide 88 text

(defmacro with-read-lock [lock & body] `(let [read-lock# (.readLock ~lock)] (try (.lock read-lock#) ~@body (finally (.unlock read-lock#))))) Syntax Quote

Slide 89

Slide 89 text

(defmacro with-read-lock [lock & body] `(let [read-lock# (.readLock ~lock)] (try (.lock read-lock#) ~@body (finally (.unlock read-lock#))))) read-lock__1234__auto__

Slide 90

Slide 90 text

(defmacro with-read-lock [lock & body] `(let [read-lock# (.readLock ~lock)] (try (.lock read-lock#) ~@body (finally (.unlock read-lock#)))))

Slide 91

Slide 91 text

(defmacro with-read-lock [lock & body] `(let [read-lock# (.readLock ~lock)] (try (.lock read-lock#) ~@body (finally (.unlock read-lock#)))))

Slide 92

Slide 92 text

(defmacro with-read-lock [lock & body] `(let [read-lock# (.readLock ~lock)] (try (.lock read-lock#) ~@body (finally (.unlock read-lock#)))))

Slide 93

Slide 93 text

“Lisp isn't a language, it's a building material” ! —Alan Kay
 Co-creator of Smalltalk

Slide 94

Slide 94 text

1st Rule Of Macros Don't Write 
 Macros

Slide 95

Slide 95 text

(defn with-read-lock [lock f] (let [read-lock (.readLock lock)] (try (.lock read-lock) (f) (finally (.unlock read-lock))))) (with-read-lock my-lock #(println my-lock))

Slide 96

Slide 96 text

Beyond the language

Slide 97

Slide 97 text

No content

Slide 98

Slide 98 text

No content

Slide 99

Slide 99 text

No content

Slide 100

Slide 100 text

No content

Slide 101

Slide 101 text

No content

Slide 102

Slide 102 text

No content

Slide 103

Slide 103 text

No content

Slide 104

Slide 104 text

No content

Slide 105

Slide 105 text

No content

Slide 106

Slide 106 text

No content

Slide 107

Slide 107 text

No content

Slide 108

Slide 108 text

No content

Slide 109

Slide 109 text

No content

Slide 110

Slide 110 text

No content

Slide 111

Slide 111 text

No content

Slide 112

Slide 112 text

No content

Slide 113

Slide 113 text

No content

Slide 114

Slide 114 text

No content

Slide 115

Slide 115 text

Wrap up

Slide 116

Slide 116 text

Not Covered Here Concurrency — Vars, Atoms, and Refs ClojureScript — Clojure in the Browser Datomic — The Database as a Value Ring, Compojure — Web and API Servers Pedestal, Reagent, Om, Hoplon — Client Frameworks core.test, midje, speclj — testing frameworks 100's of built-in functions and macros

Slide 117

Slide 117 text

Howard's Workflow 1. Terrific Idea! 2. Implement 3. Test 4. Gloat/Tweet 5. Discover it's already in clojure.core 6. Repeat

Slide 118

Slide 118 text

Power Focus Simplicity ⊙ Macros ⊙ Java Interop ⊙ Syntax ⊙ Immutability ⊙ REPL ⊙ clojure.core

Slide 119

Slide 119 text

“Simplicity and elegance are unpopular because they require hard work and discipline to achieve and education to be appreciated.” ! —Edsger Dijkstra

Slide 120

Slide 120 text

http://www.flickr.com/photos/39997856@N03/10865983036/ http://www.flickr.com/photos/ericparker/5555616243/ http://thenounproject.com/term/gears/2174/ http://www.flickr.com/photos/64958688@N00/3604756480/ http://www.flickr.com/photos/manugomi/2884678938/ http://www.flickr.com/photos/7955505@N05/489992128/ http://www.flickr.com/photos/44718043@N06/4153625805/ http://www.flickr.com/photos/skrb/5107280055/ http://www.flickr.com/photos/subconscience/297682093/ http://xkcd.com/297/ http://thenounproject.com/term/keyboard/19457

Slide 121

Slide 121 text

Links http://clojure.org http://clojure.org/cheatsheet http://kapeli.com/dash https://github.com/ technomancy/leiningen http://clojars.org http://www.lighttable.com/ https://nightcode.info/
 http://cursiveclojure.com/ https://code.google.com/p/ counterclockwise/ https://www.4clojure.com/ http://clojurekoans.com/ http://www.cognitect.com/ podcast http://howardlewisship.com

Slide 122

Slide 122 text

Q & A Howard M. Lewis Ship
 [email protected] @hlship