clojure: functional concurrency for the jvm (presented at oscon)
DESCRIPTION
A high-level overview of the Clojure functional programming language for the JVM, as presented on Jul 23 2009 at OSCON.TRANSCRIPT
![Page 1: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/1.jpg)
© 2009 Formos Software Development
Clojure: Functional Concurrency for the JVMHoward M. Lewis Ship
Director of Open Source TechnologyFormos Software Development
![Page 2: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/2.jpg)
© 2009 Formos Software Development
Clojure: The Language
http://xkcd.com/297/
![Page 3: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/3.jpg)
© 2009 Formos Software Development
Rich Hickey
![Page 4: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/4.jpg)
© 2009 Formos Software Development
Code is Data
'(1 2 3)
(biggest 5 42)
(defn biggest "Find the maximum of two numbers" [x y] (if (> x y) x y))
Quoted list of numbers
Function call
Function definition
![Page 5: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/5.jpg)
© 2009 Formos Software Development
Read Eval Print Loop
user=> (defn biggest "Find the maximum of two numbers" [x y] (if (> x y) x y))#=(var user/biggest)user=> (biggest 5 42)42user=> (doc biggest)-------------------------user/biggest([x y]) Find the maximum of two numbersniluser=> '(1 2 3)(1 2 3)user=> '(biggest 5 42)(biggest 5 42)user=> (first '(biggest 5 42))biggestuser=> (eval '(biggest 5 42))42
![Page 6: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/6.jpg)
Operating System
JVM
Java Libraries
User Classes
ClojureRepl Input
Clojure Source Files
Java Compiler
Source Code
Evaluator
© 2009 Formos Software Development
There Is No Interpreter
![Page 7: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/7.jpg)
© 2009 Formos Software Development
Clojure Literals
user=> 4242user=> "A Clojure String""A Clojure String"user=> nilniluser=> :balance:balanceuser=> truetrueuser=> falsefalse
![Page 8: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/8.jpg)
© 2009 Formos Software Development
Clojure Literals
user=> 55user=> 5.0015.001user=> 22/722/7user=> (* 2 22/7)44/7user=> (* 100000 100000 100000)1000000000000000user=> (+ 5. 0.000000000000000001)5.0user=> (+ 5.0M 0.000000000000000001M)5.000000000000000001M
![Page 9: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/9.jpg)
(.setNamespaceAware factory true)
© 2009 Formos Software Development
Java Interop
factory.setNamespaceAware(true)
new StringBuffer() (new StringBuffer)
(StringBuffer.)
factory.newSAXParser().parse(src, handler)
(.. factory newSAXParser (parse src handler))
myObject.ivar = "foo"; (set! (. myObject ivar) "foo")
![Page 10: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/10.jpg)
(doto (JFrame.) (.add panel BorderLayout/CENTER) (.add greet-button BorderLayout/SOUTH) (.pack) (.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE) (.setVisible true))
© 2009 Formos Software Development
Java Interop
frame = new JFrame();
frame.add(panel, BorderLayout.CENTER);frame.add(greetButton, BorderLayout.SOUTH);frame.pack();frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setVisible(true);
![Page 11: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/11.jpg)
1
2
3
lst
© 2009 Formos Software Development
Clojure Collections: Lists
user=> (def lst `(1 2 3))#=(var user/lst)user=> lst(1 2 3)user=> (first lst)1user=> (rest lst)(2 3)user=> (conj lst 4)(4 1 2 3)user=> (cons 4 lst)(4 1 2 3)
4
![Page 12: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/12.jpg)
© 2009 Formos Software Development
Clojure Collections: Vectors
user=> (def v [:moe :larry :curly])#=(var user/v)user=> v[:moe :larry :curly]user=> (first v):moeuser=> (rest v)(:larry :curly)user=> (conj v :shemp)[:moe :larry :curly :shemp]user=> (cons :shemp v)(:shemp :moe :larry :curly)user=> v[:moe :larry :curly]user=> (v 1):larry
vector is a function of its indexes
![Page 13: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/13.jpg)
© 2009 Formos Software Development
Clojure Collections: Map
user=> (def m {:first-name "Howard" :last-name "Lewis Ship"})#=(var user/m)user=> m{:last-name "Lewis Ship", :first-name "Howard"}user=> (get m :last-name)"Lewis Ship"user=> (m :last-name)"Lewis Ship"user=> (assoc m :company "Formos"){:company "Formos", :last-name "Lewis Ship", :first-name "Howard"}user=> m{:last-name "Lewis Ship", :first-name "Howard"}user=> (:first-name m)"Howard"user=> (:ssn m)nil
map is a function of its keys
Keywords are functions, too!
![Page 14: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/14.jpg)
© 2009 Formos Software Development
Clojure Collections: Sets
user=> (def s #{"Howard" "Suzanne" "Molly" "Jim"})#=(var user/s)user=> s#{"Howard" "Jim" "Molly" "Suzanne"}user=> (contains? s "Howard")trueuser=> (contains? s "howard")falseuser=> (s "Howard")"Howard"user=> (s "Rhys")niluser=> (conj s "Howard")#{"Howard" "Jim" "Molly" "Suzanne"}user=> (conj s "Scott")#{"Howard" "Jim" "Molly" "Suzanne" "Scott"}
set is a function of its elements
![Page 15: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/15.jpg)
© 2009 Formos Software Development
❝For alumni of other languages, beginning to use Lisp may be like stepping onto a skating rink for the first time. It’s actually much easier to get around on ice than it is on dry land—if you use skates. Till then you will be left wondering what people see in this sport.❞
Paul Graham
![Page 16: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/16.jpg)
© 2009 Formos Software Development
Functional Programming
![Page 17: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/17.jpg)
© 2009 Formos Software Development
No Mutable
State
![Page 18: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/18.jpg)
© 2009 Formos Software Development
No Side Effects
![Page 19: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/19.jpg)
© 2009 Formos Software Development
First Class Functions
![Page 20: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/20.jpg)
© 2009 Formos Software Development
Functional Composition
![Page 21: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/21.jpg)
© 2009 Formos Software Development
Functional Programming in Java
public void saveOrUpdate(final Employee employee){ HibernateCallback callback = new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException,SQLException { session.saveOrUpdate(employee); return null; } }; hibernateTemplate.execute(callback);}
SwingUtilities.invokeLater(new Runnable() { public void run() { progressBar.setValue(progressBar.getValue() + 1); } });
Outer function controls the context:• Thread• Exception handling• Parameters
![Page 22: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/22.jpg)
© 2009 Formos Software Development
Functional Java Collections
return CollectionUtils.filter(new Predicate<String>(){ public boolean accept(String value) { return !value.startsWith("."); }}, names);
public static <T> Collection<T> filter(Predicate<T> pred, Collection<T> coll){ Collection<T> out = new ArrayList<T>();
for (T item : coll) { if (pred.accept(item)) out.add(item); }
return out;}
public interface Predicate<T>{ boolean accept(T value);}
![Page 23: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/23.jpg)
© 2009 Formos Software Development
Functional Clojure Collections
(filter #(not (.startsWith % ".")) names)
Member access form
user=> (def names ["fred" "barney" ".hidden" "wilma"])#=(var user/names)user=> (filter #(not (.startsWith % ".")) names)("fred" "barney" "wilma")user=> (remove #(.startsWith % ".") names)("fred" "barney" "wilma")user=>
Anonymous function
Function parameter
![Page 24: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/24.jpg)
(defn require-extension [ext] (fn [file-name] (= ext (last (split-string file-name ".")))))
© 2009 Formos Software Development
First Class Functions
(filter #(not (.startsWith % ".")) names)
function as parameter to function
(defn filter-by-extension [ext coll] (filter (require-extension ext) coll))
function as return value
composing functions
![Page 25: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/25.jpg)
y
z
col
x
© 2009 Formos Software Development
Life without the for loop
public static int sum(int[] vals){ int total = 0;
for (int val : vals) total += val;
return total;}
(defn sum [col] (reduce + 0 col))
0 + col[0] + col[1] + col[2] ...➠
![Page 26: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/26.jpg)
© 2009 Formos Software Development
Life without the for loop
public static String[] formatDoubles(double[] inputs){ String[] output = new String[inputs.length];
for (int i = 0; i < input.length; i++) output[i] = String.format("%9.2f", inputs[i]);
return output;}
(defn format-doubles [col] (map #(format "%9.2f" %) col))
Apply function to each item, forming new seq
user=> (format-doubles '(2.5 3.7 -22.7))(" 2.50" " 3.70" " -22.70")
f
f
f
![Page 27: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/27.jpg)
© 2009 Formos Software Development
for: list comprehension
user=> (range 0 5)(0 1 2 3 4)user=> (for [x (range 0 10) :when (even? x)] x)(0 2 4 6 8)user=>
user=> (for [suit [:heart :spade :diamond :club] rank [:ace 2 3 4]] [suit rank])([:heart :ace] [:heart 2] [:heart 3] [:heart 4] [:spade :ace] [:spade 2] [:spade 3] [:spade 4] [:diamond :ace] [:diamond 2] [:diamond 3] [:diamond 4] [:club :ace] [:club 2] [:club 3] [:club 4])user=>
user=> (for [x (range 1 5) y (range 0 x)] [x y])([1 0] [2 0] [2 1] [3 0] [3 1] [3 2] [4 0] [4 1] [4 2] [4 3])user=>
![Page 28: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/28.jpg)
© 2009 Formos Software Development
Laziness is a Virtue
user=> (take 20 (iterate inc 1))(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20)user=> (take 20 (map * (iterate inc 1) (iterate inc 1)))(1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361 400)
![Page 29: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/29.jpg)
© 2009 Formos Software Development
Laziness
![Page 30: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/30.jpg)
© 2009 Formos Software Development
Java: Data Encapsulated in Objects
public double averageAge(Collection<Person> persons){ double total = 0.0;
for (Person p : persons) total += p.getAge();
return total / persons.size();}
Person
firstName: "Howard"
lastName: "Lewis Ship"
age: 42
Person
firstName: "Scott"
lastName: "Simon"
age: 44
Person
firstName: "Molly"
lastName: "Newman"
age: 29
Person
firstName: "David"
lastName: "Goldman"
age: 42
![Page 31: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/31.jpg)
© 2009 Formos Software Development
Clojure: Data in Transformable Collections
user=> persons[{:first-name "Howard", :last-name "Lewis Ship", :age 42} {:first-name "Scott", :last-name "Simon", :age 44} {:first-name "Molly", :last-name "Newman", :age 29}]user=> (map :age persons)(42 44 29)user=> (apply + (map :age persons))115user=>
(defn avg-age [coll] (/ (apply + (map :age coll)) (count coll)))
(defn avg [f coll] (/ (apply + (map f coll))) (count coll)))
(defn avg-age [coll] (avg :age coll))
(avg #(count (:last-name %)) persons)
{ }:first-name Howard
:last-name Lewis Ship
:age 42
{ }:first-name Scott
:last-name Simon
:age 44
{ }:first-name Molly
:last-name Newman
:age 29
![Page 32: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/32.jpg)
© 2009 Formos Software Development
❝Somehow the idea of reusability got attached to object-oriented programming in the 1980s, and no amount of evidence to the contrary seems to be able to shake it free.❞
Paul Graham
![Page 33: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/33.jpg)
© 2009 Formos Software Development
Clojure Concurrency
![Page 34: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/34.jpg)
© 2009 Formos Software Development
Solving Deadlocks: Timeout & Retry
![Page 35: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/35.jpg)
© 2009 Formos Software Development
Solving Deadlocks: Specific Lock Order
![Page 36: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/36.jpg)
© 2009 Formos Software Development
Solving Deadlocks:Coarse Locks
![Page 37: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/37.jpg)
© 2009 Formos Software Development
Locks are the Enemy
![Page 38: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/38.jpg)
© 2009 Formos Software Development
Clojure: Software Transactional Memory
(transfer checking savings 500.) (transfer mm checking 300.)
500.
2500.
6700.
2800.
Checking 1000.
Savings
MM
2000.
7000.
- 500. + 500. - 300. + 300.
500.
2800.
6700.
(def savings (ref 1000.))(def checking (ref 2000.))(def mm (ref 7000.)) (defn transfer "Transaction to transfer money from one account to another." [from to amount] (dosync (alter from - amount) (alter to + amount)))
![Page 39: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/39.jpg)
© 2009 Formos Software Development
Retries: Transactions Are Speculative
500.
2300.
Checking 1000.
Savings
MM
2000.
7000.
- 500.
2500.
+ 500.
6700.
- 300.
+ 300.
500.
2800.
6700.6700.
2800.
- 300. + 300.
(def savings (ref 1000.))(def checking (ref 2000.))(def mm (ref 7000.)) (defn transfer "Transaction to transfer money from one account to another." [from to amount] (dosync (alter from - amount) (alter to + amount)))
(transfer checking savings 500.) (transfer mm checking 300.)
X2500.
7000.
![Page 40: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/40.jpg)
© 2009 Formos Software Development
No Blocking
![Page 41: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/41.jpg)
© 2009 Formos Software Development
No Locks
![Page 42: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/42.jpg)
© 2009 Formos Software Development
Persistent Collections
![Page 43: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/43.jpg)
© 2009 Formos Software Development
Managing Mutation
• What can change?
• Reference types: atom, var, agent, ref
• When can they change?
• When are changes visible to other threads?
![Page 44: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/44.jpg)
© 2009 Formos Software Development
Atoms
• Shared, Global
• Changes are atomic, synchronous, & non-blocking
• (swap!): Pass value to function yielding new value
• (reset!): Force new value, regardless of existing value
user=> (def queue (atom []))#'user/queueuser=> @queue[]user=> (swap! queue conj {:parse "http://www.clojure.org/"})[{:parse "http://www.clojure.org/"}]user=> @queue[{:parse "http://www.clojure.org/"}]user=> (reset! queue [])[]user=> @queue[]user=>
![Page 45: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/45.jpg)
© 2009 Formos Software Development
Vars — Per-Thread Mutables• (def) sets global binding
• (binding) to set up a per-thread override
• (set!) if per-thread binding
user=> (def x 1)#=(var user/x)user=> x1user=> (defn manipulate-x [] (binding [x 2] (printf "Local x is %d" x) (set! x 3) (printf "\nLocal x is now %d\n" x)))#=(var user/manipulate-x)user=> (.run (Thread. manipulate-x))Local x is 2Local x is now 3niluser=> x1
![Page 46: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/46.jpg)
© 2009 Formos Software Development
(def *tokens*)
(defn add-token [token] (set! *tokens* (conj *tokens* token)))
(def sax-handler (proxy [DefaultHandler] [] (startElement [uri local-name q-name attrs] (flush-text) (add-token …)) … ))
(defn tokenize-xml [src] (binding [*tokens* []] (let [factory (SAXParserFactory/newInstance)] (.setNamespaceAware factory true) (.. factory newSAXParser (parse src sax-handler)) *tokens*)))
Interfacing with Java APIs
![Page 47: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/47.jpg)
Function
Value
...
Namespace Var
© 2009 Formos Software Development
Everything's a Var!
Symbol such as x or map
![Page 48: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/48.jpg)
© 2009 Formos Software Development
Functions are stored in Vars
user=> (defn say-hello [] (println "Hello"))#'user/say-hellouser=> (say-hello)Helloniluser=> (binding [say-hello #(println "Goodbye")] (say-hello))Goodbyeniluser=> (say-hello)Helloniluser=>
![Page 49: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/49.jpg)
user=> (def savings (agent 1000.))#=(var user/savings)user=> (def checking (agent 2000.))#=(var user/checking)user=> @savings1000user=> @checking2000user=> (send savings - 300.)#<clojure.lang.Agent@c3233b>user=> (send checking + 300.)#<clojure.lang.Agent@67e5a7>user=> @savings700user=> @checking2300
© 2009 Formos Software Development
Agents — Single Thread Writes
•Asynchonous•Single threaded•Non-transactional
![Page 50: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/50.jpg)
© 2009 Formos Software Development
Refs — Software Transactional Memory
(transfer checking savings 500.) (transfer mm checking 300.)
(def savings (ref 1000.))(def checking (ref 2000.))(def mm (ref 7000.)) (defn transfer "Transaction to transfer money from one account to another." [from to amount] (dosync (alter from - amount) (alter to + amount)))
user=> @checking2000user=> @savings1000user=> (transfer checking savings 500.)1500user=> @checking1500user=> @savings1500user=> (ref-set savings 2000.)java.lang.IllegalStateException: No transaction running (NO_SOURCE_FILE:0)
![Page 51: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/51.jpg)
© 2009 Formos Software Development
Concurrency Notes
• All reference types can have a validator function
• All refs can have a watcher: an agent notified of changes
• (send) inside (dosync) waits until successful completion
• No guarantees when calling Java objects
![Page 52: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/52.jpg)
© 2009 Formos Software Development
❝The key to performance is elegance, not battalions of special cases.❞
Jon Bentley and Doug McIlroy
![Page 53: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/53.jpg)
© 2009 Formos Software Development
Wrap Up
![Page 54: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/54.jpg)
© 2009 Formos Software Development
Clojure
• 1.0 release: May 4 2009
• Simple, regular syntax
• Improves on Lisp: vectors, maps, sets
• Fully integrates with Java
• Impressive functional & concurrency support
• Many features not covered here
http://www.clojure.org
![Page 55: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/55.jpg)
© 2009 Formos Software Development
Stuart Halloway
Pragmatic Bookshelf
http://pragprog.com/titles/shcloj/programming-clojure
![Page 56: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/56.jpg)
© 2009 Formos Software Development
http://jnb.ociweb.com/jnb/jnbMar2009.html
![Page 57: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/57.jpg)
© 2009 Formos Software Development
Object Oriented
![Page 58: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/58.jpg)
© 2009 Formos Software Development
Functional
![Page 59: Clojure: Functional Concurrency for the JVM (presented at OSCON)](https://reader034.vdocuments.us/reader034/viewer/2022051507/54b7a93c4a795913288b45cd/html5/thumbnails/59.jpg)
© 2009 Formos Software Development
Picture Credits© 2007 Jon Fifehttp://flickr.com/photos/good-karma/577632972/
© 2008 Marcin Wicharyhttp://flickr.com/photos/mwichary/2222776430/
© 2007 James Mannershttp://flickr.com/photos/jmanners/443421045/
© 2008 Daniel Chanhttp://flickr.com/photos/chanchan222/2847443980/
© 2005 Jack Keenehttp://www.flickr.com/photos/whatknot/3118124/
© A. Lipson 2003http://www.andrewlipson.com/escher/relativity.html
© 2007 Alan Chiahttp://flickr.com/photos/seven13avenue/2080281038/
© 2007 Woodley Wonderworkshttp://flickr.com/photos/wwworks/2222523486/