Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually...
Transcript of Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually...
![Page 1: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/1.jpg)
Clojure: Enemy of the State
Alex Miller @puredanger
* Not actually an enemy of the state, or state in general. :)
*
![Page 2: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/2.jpg)
Roadmap
✤ Values vs objects
✤ Collections
✤ Sequences
✤ Generic data interfaces
✤ Identity and state
![Page 3: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/3.jpg)
Precise meaning or significance.
Thing or quality having intrinsic worth.
A particular magnitude, number, or amount.
What is a "value"?
![Page 4: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/4.jpg)
Examples206.2false, truea "abc"
Propertiesprecise meaningimmutablecomparable for equalitysemantically evident
![Page 5: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/5.jpg)
What about composite values?
Value
Primitive Value
Composite Value
![Page 6: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/6.jpg)
Are objects composite values?
An object is a first-class, dynamically dispatched behavior. First class means that objects have the same capabilities as other kinds of values, including being passed to operations or returned as the result of an operation.
Objects can be used anywhere that values can be used.
Selected quotes from William Cook's modern definition of OO:http://wcook.blogspot.com/2012/07/proposal-for-simplified-modern.html
![Page 7: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/7.jpg)
Have you ever …
• struggled with how to define equality for an object?
• needed to defensively clone or copy an object?
• had issues with multithreaded access to objects?
• had trouble combining thread-safe objects?
• had trouble serializing objects?
• had trouble caching objects?
• had trouble with queuing objects?
![Page 8: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/8.jpg)
Mutableobjects
Composite values
≠
![Page 9: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/9.jpg)
![Page 10: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/10.jpg)
Roadmap
✤ Values vs objects
✤ Collections
✤ Sequences
✤ Generic data interfaces
✤ Identity and state
![Page 11: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/11.jpg)
Clojure
✤ A Lisp dialect
✤ Runs on JVM (also: ClojureScript, ClojureCLR)
✤ Dynamically typed
✤ Compiled (no interpreter)
✤ Functional programming
![Page 12: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/12.jpg)
Primitives
✤ 10
✤ 20.3
✤ 22/7
✤ false, true
✤ nil
✤ \a
✤ "abc"
![Page 13: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/13.jpg)
Clojure collections
Vectors[1 2 3]
Maps{:first-‐name "John", :last-‐name "McCarthy"}
Lists(1 2 3)
Sets#{"larry" "curly" "moe"}
![Page 14: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/14.jpg)
Clojurecollections
Composite values
=
![Page 15: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/15.jpg)
Collection functions
✤ All - count, conj, seq, into, empty
✤ List - list?, first, rest, nth, list, cons, peek, pop
✤ Vector - vector?, vector, vec, nth, subvec, replace
✤ Map - assoc, dissoc, get, select-‐keys, contains?, merge, keys, vals, find
✤ Set - set?, set, hash-‐set, disj, contains?, (clojure.set/ join, select, project, union, difference, intersection)
![Page 16: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/16.jpg)
To the demo...
![Page 17: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/17.jpg)
Isn't this all horribly inefficient?
![Page 18: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/18.jpg)
Isn't this all horribly inefficient?
![Page 19: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/19.jpg)
Isn't this all horribly inefficient?
![Page 20: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/20.jpg)
Isn't this all horribly inefficient?
![Page 21: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/21.jpg)
Isn't this all horribly inefficient?
![Page 22: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/22.jpg)
Roadmap
✤ Values vs objects
✤ Collections
✤ Sequences
✤ Generic data interfaces
✤ Identity and state
![Page 23: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/23.jpg)
Sequences
✤ Immutable view into a collection (not a stateful cursor)
✤ Also immutable composite values (logically a list)
✤ first, rest - the first and rest of the logical list
✤ seq - returns either a sequence or nil (indicating no more)
✤ Often lazy (maybe infinite!) but you can usually consider this an implementation detail
![Page 24: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/24.jpg)
What things produce sequences?
✤ All Clojure collections - list, set, vector, map✤ strings -‐ sequence of characters ✤ arrays -‐ sequence of values✤ file-‐seq -‐ files in a directory✤ line-‐seq -‐ lines in a file✤ resultset-‐seq -‐ ResultSet rows from a database✤ xml-‐seq -‐ tags in an XML doc✤ tree-‐seq -‐ a tree of collections✤ re-‐seq -‐ regular expression matches✤ iterator-‐seq -‐ Java Iterators✤ enumeration-‐seq -‐ Java Enumerations
![Page 25: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/25.jpg)
What can you do with them?
✤ distinct, filter, remove, for, keep, keep-‐indexed✤ cons, concat, lazy-‐cat, mapcat, cycle, interleave, interpose✤ rest, next, fnext, nnext, drop, drop-‐while, nthnext, for✤ flatten, reverse, sort, sort-‐by, shuffle✤ split-‐at, split-‐with, partition, partition-‐all, partition-‐by✤ map, pmap, mapcat, replace, reductions, map-‐indexed, seque✤ first, ffirst, nfirst, second, nth, when-‐first, last, rand-‐nth✤ zipmap, into, set, vec, into-‐array, to-‐array, to-‐array-‐2d,
frequencies, group-‐by, apply✤ not-‐empty, some, seq?, every?, not-‐every?, not-‐any?, empty?✤ doseq, dorun, doall, realized?✤ vals, keys, rseq, subseq, rsubseq, lazy-‐seq, repeatedly, iterate✤ repeat, range
![Page 26: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/26.jpg)
The Grand Abstraction✤ All Clojure collections✤ strings -‐ sequence of characters ✤ arrays -‐ sequence of values✤ file-‐seq -‐ files in a directory✤ line-‐seq -‐ lines in a file✤ resultset-‐seq -‐ ResultSet rows from a DB
✤ xml-‐seq -‐ tags in an XML doc✤ tree-‐seq -‐ a tree of collections✤ re-‐seq -‐ regular expression matches✤ iterator-‐seq -‐ Java Iterators✤ enumeration-‐seq -‐ Java Enumerations
![Page 27: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/27.jpg)
The Grand Abstraction✤ All Clojure collections✤ strings -‐ sequence of characters ✤ arrays -‐ sequence of values✤ file-‐seq -‐ files in a directory✤ line-‐seq -‐ lines in a file✤ resultset-‐seq -‐ ResultSet rows from a DB
✤ xml-‐seq -‐ tags in an XML doc✤ tree-‐seq -‐ a tree of collections✤ re-‐seq -‐ regular expression matches✤ iterator-‐seq -‐ Java Iterators✤ enumeration-‐seq -‐ Java Enumerations
Data
![Page 28: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/28.jpg)
The Grand Abstraction
✤ distinct, filter, remove, for, keep, keep-‐indexed
✤ cons, concat, lazy-‐cat, mapcat, cycle, interleave, interpose
✤ rest, next, fnext, nnext, drop, drop-‐while, nthnext, for
✤ flatten, reverse, sort, sort-‐by, shuffle
✤ split-‐at, split-‐with, partition, partition-‐all, partition-‐by
✤ map, pmap, mapcat, replace, reductions, map-‐indexed, seque
✤ first, ffirst, nfirst, second, nth, when-‐first, last, rand-‐nth
✤ zipmap, into, set, vec, into-‐array, to-‐array, to-‐array-‐2d, frequencies, group-‐by, apply
✤ not-‐empty, some, seq?, every?, not-‐every?, not-‐any?, empty?
✤ doseq, dorun, doall, realized?
✤ vals, keys, rseq, subseq, rsubseq, lazy-‐seq, repeatedly, iterate
✤ repeat, range
✤ All Clojure collections✤ strings -‐ sequence of characters ✤ arrays -‐ sequence of values✤ file-‐seq -‐ files in a directory✤ line-‐seq -‐ lines in a file✤ resultset-‐seq -‐ ResultSet rows from a DB
✤ xml-‐seq -‐ tags in an XML doc✤ tree-‐seq -‐ a tree of collections✤ re-‐seq -‐ regular expression matches✤ iterator-‐seq -‐ Java Iterators✤ enumeration-‐seq -‐ Java Enumerations
Data
![Page 29: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/29.jpg)
The Grand Abstraction
✤ distinct, filter, remove, for, keep, keep-‐indexed
✤ cons, concat, lazy-‐cat, mapcat, cycle, interleave, interpose
✤ rest, next, fnext, nnext, drop, drop-‐while, nthnext, for
✤ flatten, reverse, sort, sort-‐by, shuffle
✤ split-‐at, split-‐with, partition, partition-‐all, partition-‐by
✤ map, pmap, mapcat, replace, reductions, map-‐indexed, seque
✤ first, ffirst, nfirst, second, nth, when-‐first, last, rand-‐nth
✤ zipmap, into, set, vec, into-‐array, to-‐array, to-‐array-‐2d, frequencies, group-‐by, apply
✤ not-‐empty, some, seq?, every?, not-‐every?, not-‐any?, empty?
✤ doseq, dorun, doall, realized?
✤ vals, keys, rseq, subseq, rsubseq, lazy-‐seq, repeatedly, iterate
✤ repeat, range
✤ All Clojure collections✤ strings -‐ sequence of characters ✤ arrays -‐ sequence of values✤ file-‐seq -‐ files in a directory✤ line-‐seq -‐ lines in a file✤ resultset-‐seq -‐ ResultSet rows from a DB
✤ xml-‐seq -‐ tags in an XML doc✤ tree-‐seq -‐ a tree of collections✤ re-‐seq -‐ regular expression matches✤ iterator-‐seq -‐ Java Iterators✤ enumeration-‐seq -‐ Java Enumerations
Data
Code
![Page 30: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/30.jpg)
The Grand Abstraction
✤ distinct, filter, remove, for, keep, keep-‐indexed
✤ cons, concat, lazy-‐cat, mapcat, cycle, interleave, interpose
✤ rest, next, fnext, nnext, drop, drop-‐while, nthnext, for
✤ flatten, reverse, sort, sort-‐by, shuffle
✤ split-‐at, split-‐with, partition, partition-‐all, partition-‐by
✤ map, pmap, mapcat, replace, reductions, map-‐indexed, seque
✤ first, ffirst, nfirst, second, nth, when-‐first, last, rand-‐nth
✤ zipmap, into, set, vec, into-‐array, to-‐array, to-‐array-‐2d, frequencies, group-‐by, apply
✤ not-‐empty, some, seq?, every?, not-‐every?, not-‐any?, empty?
✤ doseq, dorun, doall, realized?
✤ vals, keys, rseq, subseq, rsubseq, lazy-‐seq, repeatedly, iterate
✤ repeat, range
✤ All Clojure collections✤ strings -‐ sequence of characters ✤ arrays -‐ sequence of values✤ file-‐seq -‐ files in a directory✤ line-‐seq -‐ lines in a file✤ resultset-‐seq -‐ ResultSet rows from a DB
✤ xml-‐seq -‐ tags in an XML doc✤ tree-‐seq -‐ a tree of collections✤ re-‐seq -‐ regular expression matches✤ iterator-‐seq -‐ Java Iterators✤ enumeration-‐seq -‐ Java Enumerations
Sequence
Data
Code
![Page 31: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/31.jpg)
Line counts
(defn file-‐counts [dir] (map line-‐count (filter file? (file-‐seq (file dir)))))
(defn line-‐count [file] (count (line-‐seq (reader file))))
(defn file? [file] (.isFile file))
(reduce + (file-‐counts "."))
![Page 32: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/32.jpg)
Line counts
(defn line-‐count [file] (count (line-‐seq (reader file))))
(defn file? [file] (.isFile file))
(reduce + (file-‐counts "."))
(defn file-‐counts [dir] (-‐>> dir ;; start with directory string file ;; convert to java.io.File file-‐seq ;; get sequence of files in dir (filter file?) ;; get only the files (map line-‐count))) ;; line-‐count each
![Page 33: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/33.jpg)
Roadmap
✤ Values vs objects
✤ Collections
✤ Sequences
✤ Generic data interfaces
✤ Identity and state
![Page 34: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/34.jpg)
Representing entities
firstlasttwitteremailbiopicture
Speaker
firstlasttwitteremail
Attendee
titleabstracttalktypespeakers
Talk
*organizationlevelemail
Sponsor
nameamountdescription
Leveltitleabstracttalktypespeakers
TalkType
![Page 35: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/35.jpg)
public class Speaker { private String first; private String last; private String twitterID; public Speaker(String first, String last, String twitterID) { super(); this.first = first; this.last = last; this.twitterID = twitterID; } public String getFirst() { return first; } public void setFirst(String first) { this.first = first; } public String getLast() { return last; } public void setLast(String last) { this.last = last; } public String getTwitterID() { return twitterID; } public void setTwitterID(String twitterID) { this.twitterID = twitterID; }
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((first == null) ? 0 : first.hashCode()); result = prime * result + ((last == null) ? 0 : last.hashCode()); result = prime * result
+ ((twitterID == null) ? 0 : twitterID.hashCode()); return result; }
@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Speaker other = (Speaker) obj; if (first == null) { if (other.first != null) return false; } else if (!first.equals(other.first)) return false; if (last == null) { if (other.last != null) return false; } else if (!last.equals(other.last)) return false; if (twitterID == null) { if (other.twitterID != null) return false; } else if (!twitterID.equals(other.twitterID)) return false; return true; }
@Override public String toString() { return "Speaker [first=" + first + ", last=" + last + ", twitterID=" + twitterID + "]"; }}
Custom data interface
![Page 36: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/36.jpg)
public class Speaker { private String first; private String last; private String twitterID; public Speaker(String first, String last, String twitterID) { super(); this.first = first; this.last = last; this.twitterID = twitterID; } public String getFirst() { return first; } public void setFirst(String first) { this.first = first; } public String getLast() { return last; } public void setLast(String last) { this.last = last; } public String getTwitterID() { return twitterID; } public void setTwitterID(String twitterID) { this.twitterID = twitterID; }
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((first == null) ? 0 : first.hashCode()); result = prime * result + ((last == null) ? 0 : last.hashCode()); result = prime * result
+ ((twitterID == null) ? 0 : twitterID.hashCode()); return result; }
@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Speaker other = (Speaker) obj; if (first == null) { if (other.first != null) return false; } else if (!first.equals(other.first)) return false; if (last == null) { if (other.last != null) return false; } else if (!last.equals(other.last)) return false; if (twitterID == null) { if (other.twitterID != null) return false; } else if (!twitterID.equals(other.twitterID)) return false; return true; }
@Override public String toString() { return "Speaker [first=" + first + ", last=" + last + ", twitterID=" + twitterID + "]"; }}
Custom data interface
Fields
![Page 37: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/37.jpg)
public class Speaker { private String first; private String last; private String twitterID; public Speaker(String first, String last, String twitterID) { super(); this.first = first; this.last = last; this.twitterID = twitterID; } public String getFirst() { return first; } public void setFirst(String first) { this.first = first; } public String getLast() { return last; } public void setLast(String last) { this.last = last; } public String getTwitterID() { return twitterID; } public void setTwitterID(String twitterID) { this.twitterID = twitterID; }
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((first == null) ? 0 : first.hashCode()); result = prime * result + ((last == null) ? 0 : last.hashCode()); result = prime * result
+ ((twitterID == null) ? 0 : twitterID.hashCode()); return result; }
@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Speaker other = (Speaker) obj; if (first == null) { if (other.first != null) return false; } else if (!first.equals(other.first)) return false; if (last == null) { if (other.last != null) return false; } else if (!last.equals(other.last)) return false; if (twitterID == null) { if (other.twitterID != null) return false; } else if (!twitterID.equals(other.twitterID)) return false; return true; }
@Override public String toString() { return "Speaker [first=" + first + ", last=" + last + ", twitterID=" + twitterID + "]"; }}
Custom data interface
Fields
Constructor
![Page 38: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/38.jpg)
public class Speaker { private String first; private String last; private String twitterID; public Speaker(String first, String last, String twitterID) { super(); this.first = first; this.last = last; this.twitterID = twitterID; } public String getFirst() { return first; } public void setFirst(String first) { this.first = first; } public String getLast() { return last; } public void setLast(String last) { this.last = last; } public String getTwitterID() { return twitterID; } public void setTwitterID(String twitterID) { this.twitterID = twitterID; }
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((first == null) ? 0 : first.hashCode()); result = prime * result + ((last == null) ? 0 : last.hashCode()); result = prime * result
+ ((twitterID == null) ? 0 : twitterID.hashCode()); return result; }
@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Speaker other = (Speaker) obj; if (first == null) { if (other.first != null) return false; } else if (!first.equals(other.first)) return false; if (last == null) { if (other.last != null) return false; } else if (!last.equals(other.last)) return false; if (twitterID == null) { if (other.twitterID != null) return false; } else if (!twitterID.equals(other.twitterID)) return false; return true; }
@Override public String toString() { return "Speaker [first=" + first + ", last=" + last + ", twitterID=" + twitterID + "]"; }}
Custom data interface
Fields
Constructor
Getters, setters
![Page 39: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/39.jpg)
public class Speaker { private String first; private String last; private String twitterID; public Speaker(String first, String last, String twitterID) { super(); this.first = first; this.last = last; this.twitterID = twitterID; } public String getFirst() { return first; } public void setFirst(String first) { this.first = first; } public String getLast() { return last; } public void setLast(String last) { this.last = last; } public String getTwitterID() { return twitterID; } public void setTwitterID(String twitterID) { this.twitterID = twitterID; }
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((first == null) ? 0 : first.hashCode()); result = prime * result + ((last == null) ? 0 : last.hashCode()); result = prime * result
+ ((twitterID == null) ? 0 : twitterID.hashCode()); return result; }
@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Speaker other = (Speaker) obj; if (first == null) { if (other.first != null) return false; } else if (!first.equals(other.first)) return false; if (last == null) { if (other.last != null) return false; } else if (!last.equals(other.last)) return false; if (twitterID == null) { if (other.twitterID != null) return false; } else if (!twitterID.equals(other.twitterID)) return false; return true; }
@Override public String toString() { return "Speaker [first=" + first + ", last=" + last + ", twitterID=" + twitterID + "]"; }}
Custom data interface
Fields
Constructor
Getters, setters
hashCode
![Page 40: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/40.jpg)
public class Speaker { private String first; private String last; private String twitterID; public Speaker(String first, String last, String twitterID) { super(); this.first = first; this.last = last; this.twitterID = twitterID; } public String getFirst() { return first; } public void setFirst(String first) { this.first = first; } public String getLast() { return last; } public void setLast(String last) { this.last = last; } public String getTwitterID() { return twitterID; } public void setTwitterID(String twitterID) { this.twitterID = twitterID; }
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((first == null) ? 0 : first.hashCode()); result = prime * result + ((last == null) ? 0 : last.hashCode()); result = prime * result
+ ((twitterID == null) ? 0 : twitterID.hashCode()); return result; }
@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Speaker other = (Speaker) obj; if (first == null) { if (other.first != null) return false; } else if (!first.equals(other.first)) return false; if (last == null) { if (other.last != null) return false; } else if (!last.equals(other.last)) return false; if (twitterID == null) { if (other.twitterID != null) return false; } else if (!twitterID.equals(other.twitterID)) return false; return true; }
@Override public String toString() { return "Speaker [first=" + first + ", last=" + last + ", twitterID=" + twitterID + "]"; }}
Custom data interface
Fields
Constructor
Getters, setters
hashCode
equals
![Page 41: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/41.jpg)
public class Speaker { private String first; private String last; private String twitterID; public Speaker(String first, String last, String twitterID) { super(); this.first = first; this.last = last; this.twitterID = twitterID; } public String getFirst() { return first; } public void setFirst(String first) { this.first = first; } public String getLast() { return last; } public void setLast(String last) { this.last = last; } public String getTwitterID() { return twitterID; } public void setTwitterID(String twitterID) { this.twitterID = twitterID; }
@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((first == null) ? 0 : first.hashCode()); result = prime * result + ((last == null) ? 0 : last.hashCode()); result = prime * result
+ ((twitterID == null) ? 0 : twitterID.hashCode()); return result; }
@Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Speaker other = (Speaker) obj; if (first == null) { if (other.first != null) return false; } else if (!first.equals(other.first)) return false; if (last == null) { if (other.last != null) return false; } else if (!last.equals(other.last)) return false; if (twitterID == null) { if (other.twitterID != null) return false; } else if (!twitterID.equals(other.twitterID)) return false; return true; }
@Override public String toString() { return "Speaker [first=" + first + ", last=" + last + ", twitterID=" + twitterID + "]"; }}
Custom data interface
Fields
Constructor
Getters, setters
hashCode
equals
toString
![Page 42: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/42.jpg)
Map representation
(def alex {:first "Alex" :last "Miller" :twitter "puredanger" :email "[email protected]" :bio "I like nachos." :picture "alex.jpg"})
firstlasttwitteremailbiopicture
Speaker
Where's the type?
![Page 43: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/43.jpg)
Map representation
(def alex {:first "Alex" :last "Miller" :twitter "puredanger" :email "[email protected]" :bio "I like nachos." :picture "alex.jpg" :type "Speaker"})
firstlasttwitteremailbiopicture
Speaker
![Page 44: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/44.jpg)
More entities
(def attendee {:type "Attendee" :first "Peter" :last "Gibbons" :email "[email protected]"})
(def sponsor {:type "Sponsor" :organization "Initech" :level :gold :email "[email protected]"})
firstlasttwitteremail
Attendee
organizationlevelemail
Sponsor
![Page 45: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/45.jpg)
Extracting an interface in OO
public interface Emailable { public String getEmail(); }
public class Speaker implements Emailable { private String email; public String getEmail() { return email; }}
...
![Page 46: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/46.jpg)
Preparing an email blast
(def entities (concat attendees speakers sponsors))
(map :email entities)
firstlasttwitteremail
Attendee
organizationlevelemail
Sponsorfirstlasttwitteremailbiopicture
Speaker
![Page 47: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/47.jpg)
Universal getters and setters
;; define entity(def peter {:first "peter" :last "gibbons" :email "[email protected]"})
;; associate a new key/value pair in entity(assoc peter :twitter "tps")
;; get field in entity (get peter :first)(:first peter)
![Page 48: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/48.jpg)
Access to all fields or all values
;; Get all fields in an entity(keys speaker)
;; Does speaker have a twitter or github id? (defn has-‐twitter? [speaker] (or (contains? speaker :twitter) (contains? speaker :github)))
;; Get all values in an entity(vals speaker)
![Page 49: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/49.jpg)
Traversable entities
;; Reach into nested entities (get-‐in track [:speaker :first])
;; Update inside nested entities (update-‐in track [:speaker :last] str/upper-‐case)
;; Add new key/value inside nested entities (assoc-‐in track [:speaker] {:first "..."})
![Page 50: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/50.jpg)
Walk
;; Helper function to prepend an @ to twitter id(defn prefix-‐at [entity] (if (and (associative? entity) (contains? entity :twitter)) (str "@" (:twitter entity)) entity))
;; Walk through a tree depth-‐first, post-‐order(postwalk prefix-‐at conference)
![Page 51: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/51.jpg)
Zippers
✤ Allow you to traverse and modify a tree as a functional data structure
✤ Go read about it!
![Page 52: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/52.jpg)
Records
✤ Often useful to switch behavior based on type
(defrecord Speaker [first last twitter email])
(def alex (-‐>Speaker "Alex" "Miller" "puredanger" "[email protected]"))
(class alex) ;; user.Speaker
![Page 53: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/53.jpg)
Cards demo
(defrecord Card [suit value])
(def suits [:heart :spade :diamond :club])(def values (map keyword (concat (map str (range 2 11)) ["J" "Q" "K" "A"])))(def full-‐deck (for [suit suits, value values] (-‐>Card suit value)))
(defn cut [deck] (concat (drop 26 deck) (take 26 deck)))
![Page 54: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/54.jpg)
Polymorphism
✤ Dynamically choosing code to run
✤ Conditional logic - if, cond, condp, case, etc
✤ Multimethods - switch based on arbitrary function
✤ Protocols - switch based on type
![Page 55: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/55.jpg)
Multimethods
(defmulti area :type)
(defmethod area :circle [{radius :radius}] (* 3.14159 radius radius))
(defmethod area :square [{side :side}] (* side side))
(area {:type :square :side 5})(area {:type :circle :radius 5})
Arbitrary dispatch function
![Page 56: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/56.jpg)
Protocols(defprotocol Shape (area [shape]))
(defrecord Circle [radius])(defrecord Square [side])
(extend-‐protocol Shape Circle (area [{radius :radius}] (* 3.14159 radius radius)) Square (area [{side :side}] (* side side)))
(area (-‐>Square 5))(area (-‐>Circle 5))
![Page 57: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/57.jpg)
Roadmap
✤ Values vs objects
✤ Collections
✤ Sequences
✤ Generic data interfaces
✤ Identity and state
![Page 58: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/58.jpg)
Identity
Object
title: Baconabstract: is badtalktype: Session
Talk
![Page 59: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/59.jpg)
Identity
Object
setAbstracttitle: Baconabstract: is badtalktype: Session
Talk
![Page 60: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/60.jpg)
Identity
Object
title: Baconabstract: is goodtalktype: Session
Talk'
![Page 61: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/61.jpg)
Identity
Object
setTypetitle: Baconabstract: is goodtalktype: Session
Talk'
![Page 62: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/62.jpg)
Identity
Object
title: Baconabstract: is goodtalktype: Workshop
Talk''
![Page 63: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/63.jpg)
With objects, we must be concerned with how a computational object can change and yet maintain its identity. This will force us to abandon our old substitution model of computation in favor of a more mechanistic but less theoretically tractable environment model of computation. The difficulties of dealing with objects, change, and identity are a fundamental consequence of the need to grapple with time in our computational models. These difficulties become even greater when we allow the possibility of concurrent execution of programs.
Structure and Interpretation of Computer Programs- Abelson, Sussman, and Sussman
![Page 64: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/64.jpg)
Edward Muybridge
The Horse in Motion (1878)
![Page 65: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/65.jpg)
The Horse in Motion (1878)
![Page 66: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/66.jpg)
Identity
Values State
State model
title: Baconabstract: is badtalktype: Session
Talktitle: Baconabstract: is goodtalktype: Session
Talk'title: Baconabstract: is goodtalktype: Workshop
Talk''setAbstract setType
![Page 67: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/67.jpg)
Representing state
✤ Vars - mutable storage with per thread-bindings (def)
✤ Atoms - single timeline coordination
✤ Refs - multi timeline coordination
✤ Agents - asynchronous single timeline coordination
![Page 68: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/68.jpg)
Atoms
✤ Atoms are uncoordinated synchronized state
;; Create a counter atom initialized to 0(def counter (atom 0))
;; Swap the atom to a new value(defn id [] (swap! counter inc))
(id) ;; 1(id) ;; 2(id) ;; 3
0 1 2inc inc
counter
3inc
![Page 69: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/69.jpg)
References
✤ References are for coordinated synchronous state (using STM)
;; Create references(def r1 (ref [:o]))(def r2 (ref []))
(defn yoyo [] (dosync (let [v1 @r1 v2 @r2] (ref-‐set r1 v2) (ref-‐set r2 v1)) [@r1 @r2]))(yoyo)
:oref-set
r1
:oref-set
r2
txn
![Page 70: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/70.jpg)
Agents
✤ Agents are for uncoordinated asynchronous state
;; Create agent around a vector(def error-‐log (agent []))
;; Log a message by sending a function to the agent(defn log [msg] (send-‐off error-‐log conj msg))
(log "hi")(log "there");; Deref to observe the agent@error-‐log
[] ["hi"] ["hi" "there"]conj conj
error-log
queue
![Page 71: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/71.jpg)
To sum up...
✤ Objects are not composite values
✤ Collections - are immutable composite values
✤ Sequences - unifies composite values with FP
✤ Generic data interface - powerful tools for manipulating entities
✤ Identity and state - reference types separate identity from value
![Page 72: Clojure: Enemy of the State · Clojure: Enemy of the State Alex Miller @puredanger * Not actually an enemy of the state, or state in general. :) *](https://reader031.fdocuments.in/reader031/viewer/2022012918/5fdd12855788755455087d49/html5/thumbnails/72.jpg)
References
✤ More on values and state:
✤ http://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hickey
✤ http://www.infoq.com/presentations/Value-Values
✤ Find me here:
✤ @puredanger
✤ http://tech.puredanger.com