8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 1/152
Copyright 2007-2009 Relevance, Inc. This presentation is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License. See http://creativecommons.org/licenses/by-nc-sa/3.0/us/
stuart halloway
1
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 2/152
clojure’s four elevators java interop
lisp
functionalstate
2
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 3/152
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 4/152
java new
java new Widget( "foo" )
clojure ( new Widget "foo" )
clojure sugar (Widget . "red" )
4
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 5/152
access static members
java Math.PI
clojure (. Math PI)
clojure sugar Math/PI
5
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 6/152
access instance members
java rnd.nextInt()
clojure (. rnd nextInt)
clojure sugar (.nextInt rnd)
6
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 7/152
chaining access
java person.getAddress().getZipCode()
clojure (. (. person getAddress) getZipCode)
clojure sugar (.. person getAddress getZipCode)
7
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 8/152
parenthesis count
java ()()()()
clojure ()()()
8
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 9/152
atomic data typestype example java equivalentstring "foo" String
character \f Character
regex #"fo*" Pattern
a. p. integer 42 Integer/Long/BigInteger
double 3.14159 Double
a.p. double 3.14159M BigDecimal
boolean TRUE Booleannil nil null
symbol foo, + N/A
keyword :foo, ::foo N/A9
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 10/152
example:refactor apache
commons isBlank 10
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 11/152
public class StringUtils {public static boolean isBlank( String str) {
int strLen;if (str == null || (strLen = str.length()) == 0 ) {
return true ;}for (int i = 0 ; i < strLen; i ++) {
if (( Character .isWhitespace(str.charAt(i)) == false )) {return false ;
}}
return true ;}
}
initial implementation
11
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 12/152
public class StringUtils {public isBlank(str) {
if (str == null || (strLen = str.length()) == 0 ) {return true ;
}
for (i = 0 ; i < strLen; i ++) {if (( Character .isWhitespace(str.charAt(i)) == false )) {
return false ;}
} return true ;
}}
- type decls
12
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 13/152
public isBlank(str) {if (str == null || (strLen = str.length()) == 0 ) {
return true ;}
for (i = 0 ; i < strLen; i ++) {if (( Character .isWhitespace(str.charAt(i)) == false )) {
return false ;}
} return true ;}
- class
13
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 14/152
public isBlank(str) {if (str == null || (strLen = str.length()) == 0 ) {
return true ;}every (ch in str) {
Character .isWhitespace(ch);}
return true ;}
+ higher-order function
14
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 15/152
public isBlank(str) {
every (ch in str) {Character .isWhitespace(ch);
}}
- corner cases
15
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 16/152
( defn blank? [ s ] ( every? #(Character/isWhitespace %) s))
lispify
16
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 17/152
clojure is a better java than java
17
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 18/152
2. lisp
18
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 19/152
what makes lisp different
http://www.paulgraham.com/diff.html
feature industrynorm
coolkids clojure
conditionals
variables
garbage collection
recursion
function type
symbol type
whole language available
everything’s an expressionhomoiconicity
19
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 20/152
foo.bar(x,y,z);
foo.bar x y z
regular code
20
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 21/152
special formsimports
scopes
protection
metadata
control ow
anything using a keyword
21
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 22/152
outside lisp, special formslook different
may have special semantics unavailable to you
prevent reuse
22
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 23/152
in a lisp, special formslook just like anything else
may have special semantics available to you
can be augmented with macros
23
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 24/152
all forms created equal
form syntax example
function list (println "hello")operator list (+ 1 2)
method call list (.trim " hello ")import list (require 'mylib)
metadata list (with-meta obj m)control ow list (when valid? (proceed))
scope list (dosync (alter ...))
24
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 25/152
who cares?
25
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 26/152
26
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 27/152
clojure is turning
the tide in a fty-year struggleagainst bloat
27
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 28/152
game break!
28
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 29/152
Sample Code:http://github.com/stuarthalloway/programming-clojure
29
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 30/152
( defn describe [ snake ]( println "head is " ( first snake))( println "tail is" ( rest snake)))
early impl:a snake
is a sequenceof points rst point is
head
rest is tail
30
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 31/152
( defn describe [[ head & tail ]]( println "head is " head)( println "tail is" tail))
destructurerst elementinto head
captureremainder as a
sequence
destructure remainingelements into tail
31
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 32/152
( defn create-snake [] { :body ( list [ 1 1 ] )
:dir [ 1 0 ] :type :snake :color (Color . 15 160 70) })
snake is more than location
32
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 33/152
( defn describe [ {[ head & tail ] :body }]( println "head is " head)( println "tail is" tail))
2. nested destructureto pull head and tail from the
:body value
1. destructure map,looking up the :tail
33
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 34/152
( defn lose? [ {[ head & tail ] :body }](includes? tail head))
losing the game
34
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 35/152
3. functional
35
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 36/152
data literalstype properties example
list singly-linked,insert at front ( 1 2 3 )
vector indexed,insert at rear [ 1 2 3 ]
map key/value {:a 100:b 90 }
set key #{ :a :b }
36
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 37/152
higher-orderfunctions
37
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 38/152
lunch-companions
-> ( { :fname "Neal" , :lname "Ford" } { :fname "Stu" , :lname "Halloway" } { :fname "Dan" , :lname "North" })
some data
38
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 39/152
( defn last-name [ x]( get x :last-name )
“getter” functionfn name arg list (vector)
body
39
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 40/152
(sort-byfirst-namelunch-companions)
-> ( { :fname "Dan" , :lname "North" } { :fname "Neal" , :lname "Ford" } {:fname "Stu" , :lname "Halloway" })
pass fn to fncall fn
fn arg
data arg
40
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 41/152
(sort-by( fn [ n]( get n :fname ))
lunch-companions)
anonymous fn
anonymous fn
fn arg
body
41
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 42/152
(sort-by#( get % :fname )lunch-companions)
anonymous #()
anonymous fn
fn arg
42
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 43/152
(sort-by#(% :fname )lunch-companions)
maps are functions
map is fn!
43
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 44/152
(sort-by#( :fname %)lunch-companions)
keywords are functionskeyword
is fn!
44
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 45/152
(sort-by :fname lunch-companions)
beautiful
45
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 46/152
real languages
give a 1-1 ratio of pseudocode/code
46
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 47/152
persistent datastructures
47
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 48/152
persistent data structuresimmutable
“change” by function application
maintain performance guarantees
full-delity old versions
48
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 49/152
persistent example:
linked list
tigerrabbitternnewt
“my” list“your”list
49
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 50/152
bit-partitioned tries
“your”trie
“my”trie
50
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 51/152
log2 n:too slow!
51
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 52/152
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 53/152
clojure: ‘causelog32 n is
fast enough!53
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 54/152
sequencelibrary
54
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 55/152
( first [ 1 2 3 ] )-> 1
( rest [ 1 2 3 ] )-> (2 3)
( cons "hello" [ 1 2 3 ] )-> ( "hello" 1 2 3)
rst / rest / cons
55
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 56/152
( take 2 [ 1 2 3 4 5 ] )-> (1 2)
( drop 2 [ 1 2 3 4 5 ] )-> (3 4 5)
take / drop
56
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 57/152
( range 10)-> (0 1 2 3 4 5 6 7 8 9)
( filter odd? ( range 10))-> (1 3 5 7 9)
( map odd? ( range 10))-> (false true false true false truefalse true false true)
( reduce + ( range 10))-> 45
map / lter / reduce
57
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 58/152
( sort [ 1 56 2 23 45 34 6 43 ] )-> (1 2 6 23 34 43 45 56)
( sort > [ 1 56 2 23 45 34 6 43 ] )-> (56 45 43 34 23 6 2 1)
( sort-by #(.length %)[ "the" "quick" "brown" "fox" ] )-> ( "the" "fox" "quick" "brown" )
sort
58
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 59/152
( conj '(1 2 3) :a )-> ( :a 1 2 3)
( into '(1 2 3) '( :a :b :c ))-> ( :c :b :a 1 2 3)
( conj [ 1 2 3 ] :a )
-> [ 1 2 3 :a ] ( into [ 1 2 3 ] [ :a :b :c ] )-> [ 1 2 3 :a :b :c ]
conj / into
59
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 60/152
( set! *print-length* 5)-> 5
( iterate inc 0)-> (0 1 2 3 4 ...)
( cycle [ 1 2 ] )
-> (1 2 1 2 1 ...)( repeat :d )-> ( :d :d :d :d :d ...)
lazy, innite sequences
60
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 61/152
( interpose \, [ "list" "of" "words" ] )-> ( "list" \, "of" \, "words" )
( apply str ( interpose \, [ "list" "of" "words" ] ))
-> "list,of,words"
( use 'clojure.contrib.str-utils)( str - join \, [ "list" "of" "words" ] ))-> "list,of,words"
interpose
61
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 62/152
( every? odd? [ 1 3 5 ] )-> true
( not-every? even? [ 2 3 4 ] )-> true
( not-any? zero? [ 1 2 3 ] )
-> true( some nil? [ 1 nil 2 ] )-> true
predicates
62
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 63/152
( def jdoe {:name "John Doe" ,:address { :zip 27705, ... }} )
( get-in jdoe [ :address :zip ] )-> 27705
( assoc-in jdoe [ :address :zip ] 27514)-> {:name "John Doe" , :address { :zip 27514 }}
( update-in jdoe [ :address :zip ] inc )-> {:name "John Doe" , :address { :zip 27706 }}
nested ops
63
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 64/152
Ash zna durbatulûk,ash zna gimbatul,ash zna thrakatulûk
agh burzum-ishikrimpatul.
64
h
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 65/152
where are we?1. java interop2. lisp
3. functional
does it work?
65
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 66/152
example:
refactor apachecommonsindexOfAny
66
d f b h
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 67/152
StringUtils .indexOfAny(null, *) = - 1StringUtils .indexOfAny( "" , *) = - 1StringUtils .indexOfAny( *, null) = - 1StringUtils .indexOfAny( *, []) = - 1StringUtils .indexOfAny( "zzabyycdxx" ,[ 'z' , 'a' ]) = 0StringUtils .indexOfAny( "zzabyycdxx" ,[ 'b' , 'y' ]) = 3StringUtils .indexOfAny( "aba" , [ 'z' ]) = - 1
indexOfAny behavior
67
i d Of i l
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 68/152
// From Apache Commons Lang , http: // commons.apache.org / lang /public static int indexOfAny( String str, char[] searchChars){ if (isEmpty(str) || ArrayUtils .isEmpty(searchChars)) { return - 1;
} for (int i = 0; i < str.length(); i ++) {
char ch = str.charAt(i); for (int j = 0; j < searchChars.length; j ++) { if (searchChars[j] == ch) { return i;
}}
} return - 1;}
indexOfAny impl
68
i lif
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 69/152
public static int indexOfAny( String str, char[] searchChars){ when (searchChars)
for (int i = 0; i < str.length(); i ++) {char ch = str.charAt(i); for (int j = 0; j < searchChars.length; j ++) { if (searchChars[j] == ch) { return i;
}}
}}}
simplify corner cases
69
d l
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 70/152
indexOfAny(str, searchChars) { when (searchChars) for (i = 0; i < str.length(); i ++) {
ch = str.charAt(i); for (j = 0; j < searchChars.length; j ++) { if (searchChars[j] == ch) { return i;
}}
}}
}
- type decls
70
h l
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 71/152
indexOfAny(str, searchChars) { when (searchChars) for (i = 0; i < str.length(); i ++) {
ch = str.charAt(i); when searchChars(ch) i;
}}
}
+ when clause
71
h i
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 72/152
indexOfAny(str, searchChars) { when (searchChars) for ([i, ch] in indexed(str)) { when searchChars(ch) i;
}}
}
+ comprehension
72
li if !
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 73/152
( defn index-filter [ pred coll ]( when pred
( for [[ idx elt ] (indexed coll) :when (pred elt) ] idx)))
lispify!
73
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 74/152
functionalis
simpler 74
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 75/152
imperative functional
functions 1 1classes 1 0
internal exit points 2 0
variables 3 0
branches 4 0
boolean ops 1 0
function calls* 6 3
total 18 4
75
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 76/152
functionalis
more general!76
i i d lt
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 77/152
; idxs of heads in stream of coin flips(index-filter # { :h }
[ :t :t :h :t :h :t :t :t :h :h ] )-> (2 4 8 9)
; Fibonaccis pass 1000 at n=17( first
(index-filter #(> % 1000) (fibo)))-> 17
reusing index-lter
77
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 78/152
imperative functional
searches strings searches any sequence
matches characters matches any predicate
returns rst match returns lazy seq of all
matches
78
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 79/152
fp reduces incidentalcomplexity by an
order of magnitude
79
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 80/152
4. concurrency
80
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 81/152
4. stateconcurrency
81
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 82/152
oo is incoherentidentity
???
identity???
?
82
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 83/152
clojureidentity value
identity value
value
explicit semantic
state
83
terms
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 84/152
terms1. value: immutable data in a persistent datastructure
2. identity: series of causally related values
over time3. state: identity at a point in time
84
identity types (references)
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 85/152
identity types (references)
shared isolated
synchronous/coordinated refs/stm -
synchronous/autonomous atoms vars
asynchronous/autonomous agents -
85
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 86/152
identity 1:refs and stm
86
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 87/152
reading value
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 88/152
( deref messages)=> ()
@messages=> ()
reading value
88
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 89/152
updating
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 90/152
( defn add-message [ msg ]( dosync ( alter messages conj msg)))
updatingapply an...
scope atransaction
...update fn
90
unied update model
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 91/152
unied update modelupdate by function applicationreaders require no coordination
readers never block anybody
writers never block readers
91
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 92/152
a sane approachto local state
permits coordination,
but does not require it
92
unied update model
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 93/152
unied update modelref atom agent var
create ref atom agent def
deref deref/@ deref/@ deref/@ deref/@
update alter swap! sendalter-
var-root
93
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 94/152
identity 2:atoms
94
http://blog.bestinclass.dk/index.php/2009/10/brians-functional-brain/
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 95/152
95
board is just a value
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 96/152
( defn new-board "Create a new board with about half the cells set
to :on."( [] ( apply new-board dim-board))( [ dim-x dim-y ]
( for [ x ( range dim-x) ]( for [ y ( range dim-y) ]
( if (< 50 ( rand-int 100)) :on :off ))))))
board is just a value
distinct bodies by arity
96
update is just a function
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 97/152
( defn step "Advance the automation by one step, updating all
cells." [ board ]
(doall( map ( fn [ window ]
( apply #( doall ( apply map rules %&))( doall ( map torus-window window))))
(torus-window board))))
update is just a function
rules
cursor over previous, me, next
97
state is trivial
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 98/152
( let [ stage (atom (new-board))]...)
( defn update-stage "Update the automaton." [ stage ]
(swap ! stage step))
state is trivial
identity initial value
apply a fn update fn
98
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 99/152
send
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 100/152
sendcaller xed thread
pool( send a fn & args)
( apply fn oldval args)
agent
100
state is trivial
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 101/152
( def *logging-agent* ( agent nil))
( if log-immediately?(impl-write ! log-impl level msg err)( send-off *logging-agent*
agent-write ! log level msg err))
state is trivial
identity initial value
apply a fn “update” fn
101
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 102/152
identity 4:vars
102
def forms create vars
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 103/152
( def greeting "hello" )
( defn make-greeting [ n]( str "hello, " n)
def forms create vars
103
vars can be rebound
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 104/152
vars can be rebound
api scope
alter-var-root root binding
set! thread-local, permanent
binding thread-local, dynamic
104
system settings
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 105/152
( set! *print-length* 20)=> 20
primes
=> (2 3 5 7 11 13 17 19 23 29 31 37 4143 47 53 59 61 67 71 ...)
( set! *print-length* 5)=> 5
primes=>(2 3 5 7 11 ...)
system settings
105
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 106/152
var usage
*in*, *out*, *err* standard streams
*print-length*,*print-depth* structure printing
*warn-on-reflection* performance tuning
*ns* current namespace
*file* le being evaluated
*command-line-args* guess
106
with- helper macros
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 107/152
( def bar 10)-> #'user/bar
( with-ns 'foo ( def bar 20))-> #'foo/bar
user/bar-> 10
foo/bar-> 20
with ... helper macros
bind a varfor a dynamic
scope
107
other def forms
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 108/152
form usagedefonce set root binding once
defvar var plus docstring
defunbound no initial binding
defstruct map with slots
defalias same metadata as original
defhinted infer type from initial binding
defmemo defn + memoize
other def forms
many of these are in clojure.contrib.def...108
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 109/152
identity:more options
109
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 110/152
use commutewhen updatecan happen
anytime110
not safe for commute
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 111/152
( defn next-id "Get the next available id."
[](dosync
( alter ids inc )))
not safe for commute
111
safe!
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 112/152
( defn increment-counter "Bump the internal count." []
(dosync( alter ids inc ))
nil)
safe!
112
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 113/152
prefer send-off
if agent ops
might block 113
send
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 114/152
sendcaller xed thread
pool( send a fn & args)
( apply fn oldval args)
agent
114
send off
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 115/152
send-off caller agent
cached thread pool
( apply fn oldval args)
( send a fn & args)
115
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 116/152
use ref-set to setinitial/base state
116
unied update, revisited
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 117/152
unied update, revisitedupdatemechanism ref atom agent
pure functionapplication alter swap! send
pure function(commutative) commute - -
pure function(blocking) - - send-off
setter ref-set reset! -
117
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 118/152
send-off to *agent*
for backgrounditeration
118
monte carlo via
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 119/152
( defn background-pi [ iter- count ]( let
[ agt ( agent { :in-circle 0 :total 0})continue (atom true)iter ( fn sim [ a- val ]
( when continue ( send-off *agent* sim))(run-simulation a- val iter- count )) ]
( send-off agt iter) { :guesser agt :continue atom })
o te ca o v a
ongoing agent
do thework
queue morework
escape hatch
119
(not= agents actors)
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 120/152
( g )
agents actors
in-process only oop
no copying copying
no deadlock can deadlock
no coordination can coordinate
120
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 121/152
validation
121
create afunction that checks
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 122/152
( def validate-message-list( partial
every? #( and ( :sender %) ( :text %))))
( def messages( ref
()
:validator validate-message-list))
every item...
for some criteria
and associate fn with updates to a ref
122
agent error handling
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 123/152
( def counter ( agent 0 :validator integer? ))-> #'user/counter
( send counter ( constantly :fail ))-> #<Agent 0>
( agent-errors counter)-> (#<IllegalStateException
java.lang.IllegalStateException:Invalid reference state>)
( clear-agent-errors counter)-> nil
@counter-> 0
g g
will fail soon
list of errors
reset and move on
123
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 124/152
agents
andtransactions
124
tying agent to a tx
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 125/152
( defn add-message-with-backup [ msg ]
( dosync ( let [ snapshot ( alter messages conj msg) ]( send-off backup-agent ( fn [ filename ]
(spit filename snapshot)filename))
snapshot)))
y g g
exactly once if tx succeeds
125
where are we?
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 126/152
1. java interop2. lisp
3. functional
4. value/identity/state
does it work?
126
a workable approach to state
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 127/152
good values: persistent data structuresgood identities: references
mostly functional?
usable by mortals?
127
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 128/152
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 129/152
1 line in 1000
creates areference
129
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 130/152
project loc calls to
ref
calls to
agent
calls to
atom
clojure 7232 3 1 2
clojure-contrib 17032 22 2 12
compojure 1966 1 0 0
incanter 6248 1 0 0
130
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 131/152
usable bymortals?
131
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 132/152
; compojure session management( def memory-sessions ( ref {} ))
( defmethod read-session :memory [ repository id ]
(@memory-sessions id))
( defmethod write-session :memory [ repository session ]
(dosync( alter memory-sessions
assoc (session :id ) session)))
multimethoddispatch
read update
132
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 133/152
; from clojure core( defn memoize [ f ]
( let [ mem (atom {} ) ]( fn [ & args ]
( if-let [ e ( find @mem args) ]( val e)( let [ ret ( apply f args) ]
(swap ! mem assoc args ret)ret)))))
cache previousresults
cache hit
cache miss:call f, add to
cache
133
clojure
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 134/152
values areimmutable, persistent
identities are
well-specied, consistent
state ismostly functional
usable by mortals
134
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 135/152
languages thatemphasizeimmutability are
better at mutation135
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 136/152
timemanagement
136
prepare to parallelize
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 137/152
( defn step "Advance the automation by one step, updating all
cells."
[ board ](doall
( map ( fn [ window ]( apply #( doall ( apply map rules %&))
( doall ( map torus-window window))))(torus-window board))))
137
done
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 138/152
( defn step "Advance the automation by one step, updating all
cells."
[ board ](doall
( p map ( fn [ window ]( apply #( doall ( apply map rules %&))
( doall ( map torus-window window))))(torus-window board))))
138
delay
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 139/152
( def e ( delay (expensive-calculation)))
-> #'demo.delay/e
( delay? e)-> true
( force e)-> :some-result
( deref e)
-> :some-result
@e-> :some-result
rst call blocksuntil work
completes onthis thread,later calls hit
cache
139
future
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 140/152
( def e1 (future (expensive-calculation)))-> #'demo.future/e1
( deref e1)-> :some-result
@e1-> :some-result
rst call blocksuntil work completes on
other thread,later calls hit
cache
140
cancelling a future
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 141/152
( def e2 (future (expensive-calculation)))-> #'demo.future/e2
(future-cancel e2)-> true
(future-cancelled? e2)-> true
( deref e2)-> java.util.concurrent.CancellationException
141
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 142/152
transients
142
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 143/152
build structureon one thread,then release into
the wild143
persistent...
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 144/152
( defn vrange [ n ]( loop [ i 0 v []]
( if (< i n)( recur ( inc i) ( conj v i))v)))
144
...to transient
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 145/152
( defn vrang2 [ n ]( loop [ i 0 v ( transient [])]
( if (< i n)( recur ( inc i) ( conj! v i))( persistent v))))
enter transient world
use transient updaterreturn topersistent world
145
fast!
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 146/152
( time ( def v (vrange 1000000)))"Elapsed time: 1130.721 msecs"
( time ( def v2 (vrange2 1000000)))"Elapsed time: 82.191 msecs"
146
transients
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 147/152
usage:transient
bang updates: assoc! conj! etc.
persistent!optimization, not coordination
O(1) creation from persistent object
fast, isolated updates
O(1) conversion back to persistent object
147
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 148/152
oo: one identity ts all
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 149/152
y
state
behavior
constructors
encapsulationthread-safety
functions
validation
dispatch
identity
149
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 150/152
clojure: bespoke
code in an off-the-rack world
150
clojure’s four elevators
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 151/152
java interoplisp
functional
state
151
Email: [email protected] Office: 919-442-3030Twitter: twitter.com/stuarthallowayFacebook: stuart.hallowayGi h b h ll
8/14/2019 Http://Github.com/Stuarthalloway/Clojure Presentations
http://slidepdf.com/reader/full/httpgithubcomstuarthallowayclojure-presentations 152/152
Github: stuarthallowayThis talk: http://github.com/stuarthalloway/clojure-presentationsTalks: http://blog.thinkrelevance.com/talksBlog: http://blog.thinkrelevance.com Book: http://tinyurl.com/clojure