SlideShare a Scribd company logo
1 of 80
Clojure:
Functional
Concurrency for
the JVM
Howard M. Lewis Ship

Director of Open Source Technology
Formos Software Development

howard.lewis.ship@formos.com

                                     © 2009 Formos Software Development
Clojure: The Language

                   © 2009 Formos Software Development
http://xkcd.com/297/




Clojure: The Language

                       © 2009 Formos Software Development
Rich Hickey




              © 2009 Formos Software Development
Code is Data


                 Quoted list of
'(1 2 3)         numbers




(biggest 5 42)                Function call

                                       Function definition


(defn biggest
 "Find the maximum of two numbers"
 [x y]
 (if (> x y) x y))

                                                            © 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)
         42
         user=> (doc biggest)
         -------------------------
         user/biggest
         ([x y])
           Find the maximum of two numbers
         nil
         user=> '(1 2 3)
         (1 2 3)
         user=> '(biggest 5 42)
         (biggest 5 42)
         user=> (first '(biggest 5 42))
         biggest
         user=> (eval '(biggest 5 42))
         42

                                               © 2009 Formos Software Development
There Is No Interpreter



                                                 Source Code

Repl Input                 Clojure
                                  User Classes        Java
               Evaluator
                                                    Compiler
  Clojure
Source Files          Java Libraries

                            JVM

                    Operating System


                                                 © 2009 Formos Software Development
Clojure Literals



           user=> 42
           42
           user=> "A Clojure String"
           "A Clojure String"
           user=> nil
           nil
           user=> :balance
           :balance
           user=> true
           true
           user=> false
           false




                                       © 2009 Formos Software Development
Clojure Literals



           user=> 5
           5
           user=> 5.001
           5.001
           user=> 22/7
           22/7
           user=> (* 2 22/7)
           44/7
           user=> (* 100000 100000 100000)
           1000000000000000
           user=> (+ 5. 0.000000000000000001)
           5.0
           user=> (+ 5.0M 0.000000000000000001M)
           5.000000000000000001M




                                                   © 2009 Formos Software Development
Java Interop


factory.setNamespaceAware(true)                       (.setNamespaceAware factory true)


new StringBuffer()                                                 (new StringBuffer)

                                                                               (StringBuffer.)



factory.newSAXParser().parse(src, handler)

                                             (.. factory newSAXParser (parse src handler))




MyObject.ivar = "foo";                                        (set! (. MyObject ivar) "foo")




                                                                        © 2009 Formos Software Development
Java Interop



frame.add(panel, BorderLayout.CENTER);
frame.add(greetButton, BorderLayout.SOUTH);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);


                       (doto frame
                        (.add panel BorderLayout/CENTER)
                        (.add greet-button BorderLayout/SOUTH)
                        (.pack)
                        (.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE)
                        (.setVisible true))




                                                                    © 2009 Formos Software Development
Clojure Collections: Lists




                            lst
user=> (def lst `(1 2 3))
#=(var user/lst)
user=> lst
(1 2 3)
user=> (first lst)
1                             1
user=> (rest lst)
(2 3)
user=> (conj lst 4)               2
(4 1 2 3)
user=> (cons 4 lst)
(4 1 2 3)                             3


                                      © 2009 Formos Software Development
Clojure Collections: Lists




                            4
                                lst
user=> (def lst `(1 2 3))
#=(var user/lst)
user=> lst
(1 2 3)
user=> (first lst)
1                                 1
user=> (rest lst)
(2 3)
user=> (conj lst 4)                   2
(4 1 2 3)
user=> (cons 4 lst)
(4 1 2 3)                                 3


                                          © 2009 Formos Software Development
Clojure Collections: Vectors


          user=> (def v [:moe :larry :curly])
          #=(var user/v)
          user=> v
          [:moe :larry :curly]
          user=> (first v)
          :moe
          user=> (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

                                                © 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"                                         map is a
 user=> (m :last-name)                                function of
 "Lewis Ship"
                                                      its keys
 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
                                          Keywords are
                                          functions, too!

                                                                     © 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")
 true
 user=> (contains? s "howard")
 false                                         set is a
 user=> (s "Howard")                           function of
 "Howard"                                      its elements
 user=> (s "Rhys")
 nil
 user=> (conj s "Howard")
 #{"Howard" "Jim" "Molly" "Suzanne"}
 user=> (conj s "Scott")
 #{"Howard" "Jim" "Molly" "Suzanne" "Scott"}




                                                              © 2009 Formos Software Development
© 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
                                   © 2009 Formos Software Development
Functional Programming

                  © 2009 Formos Software Development
Functional Programming

                  © 2009 Formos Software Development
© 2009 Formos Software Development
No
Mutable
 State© 2009 Formos Software Development
© 2009 Formos Software Development
No Side
Effects
     © 2009 Formos Software Development
© 2009 Formos Software Development
First Class
Functions
         © 2009 Formos Software Development
© 2009 Formos Software Development
Functional
Composition
         © 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);
}


                                                            Outer function controls the
    SwingUtilities.invokeLater(new Runnable()               context:
    {
      public void run()                                     • Thread
      {                                                     • Exception handling
        progressBar.setValue(progressBar.getValue() + 1);
      }                                                     • Parameters
    });
                                                                           © 2009 Formos Software Development
Functional Java Collections

public interface Predicate<T>
{
  boolean accept(T value);
}


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;
}


return CollectionUtils.filter(new Predicate<String>()
{
  public boolean accept(String value)
  {
    return !value.startsWith(".");
  }
}, names);


                                                                               © 2009 Formos Software Development
Functional Clojure Collections

                                    Function
             Anonymous             parameter
              function

         (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=>




                                                             © 2009 Formos Software Development
First Class Functions
     (filter #(not (.startsWith % ".")) names)




                                 function as
                                 parameter to
                                 function



  (defn require-extension [ext]
   (fn [file-name]
     (= ext (last (split-string file-name ".")))))




                    function as
                    return value

 (defn filter-by-extension [ext coll]
  (filter (require-extension ext) coll))




                         composing functions
                                                    © 2009 Formos Software Development
Bridging Java and Clojure

SwingUtilities.invokeLater(new Runnable()
{
  public void run()
  {
    progressBar.setValue(progressBar.getValue() + 1);
  }
});




                   Invoke static method


(SwingUtilities/invokeLater
  #(.setValue progressBar (inc (.getValue progressBar))))




                                                            Clojure functions implement:
                                                            • Runnable
                                                            • Callable
                                                            • Comparator

                                                                           © 2009 Formos Software Development
Life without the for loop

public static int sum(int[] vals)
{
  int total = 0;
                                                             col

    for (int val : vals) total += val;

    return total;
}

                                                               x


                                                                            y

(defn sum                                                                       z
 [col]
 (reduce + 0 col))
                                   ➠     0 + col[0] + col[1] + col[2] ...




                                                                                © 2009 Formos Software Development
Life without the for loop

public static int sum(int[] vals)
{
  int total = 0;
                                                               col

    for (int val : vals) total += val;

    return total;
}

                                                                 x


                                                                                  y

(defn sum                                                                                      z
 [col]
 (reduce + 0 col))
                                   ➠      0 + col[0] + col[1] + col[2] ...
               ➠




                         (+ 0 (first col))
                       (+ (+ 0 (first col)) (first (rest col)))
                     (+ (+ (+ 0 (first col)) (first (rest col))) (first (rest (rest col)))) ...

                                                                                               © 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
                                                             f
   [col]
   (map #(format "%9.2f" %) col))
                                                             f
Apply function to
each item, forming                                           f
new seq

  user=> (format-doubles '(2.5 3.7 -22.7))
  ("  2.50" " 3.70" " -22.70")


                                                          © 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=> (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])




                                                                © 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=> (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])




(defn convert-attributes-to-tokens
 [attrs]
 (for [x (range (.getLength attrs))]
       (let [uri (.getURI attrs x)
            name (.getLocalName attrs x)
            value (.getValue attrs x)
            token (…) ]
          token)))



                                                                © 2009 Formos Software Development
Laziness is
                                                a Virtue




Image © 2007 Jon Fife
http://flickr.com/photos/good-karma/577632972/        © 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)

Image © 2007 Jon Fife
http://flickr.com/photos/good-karma/577632972/                               © 2009 Formos Software Development
Laziness




           © 2009 Formos Software Development
Java: Data Encapsulated in Objects

              Person                     Person              Person                Person


       firstName: "Howard"          firstName: "Scott"     firstName: "Molly"     firstName: "David"
     lastName: "Lewis Ship"       lastName: "Simon"    lastName: "Newman"    lastName: "Goldman"
             age: 42                    age: 44               age: 29               age: 42




          public double averageAge(Collection<Person> persons)
          {
            double total = 0.0;

              for (Person p : persons)
               total += p.getAge();

              return total / persons.size();
          }




                                                                                  © 2009 Formos Software Development
Clojure: Data in Transformable Collections
      :first-name     Howard              :first-name    Scott              :first-name         Molly


 {     :last-name   Lewis Ship
                                 } {     :last-name    Simon
                                                                }{         :last-name      Newman
                                                                                                          }
          :age         42                   :age        44                    :age            29



     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))
     115
     user=>




                                                                                        © 2009 Formos Software Development
Clojure: Data in Transformable Collections
       :first-name    Howard                :first-name    Scott            :first-name         Molly


 {     :last-name   Lewis Ship
                                 } {        :last-name   Simon
                                                                 }{        :last-name      Newman
                                                                                                          }
          :age         42                      :age       44                  :age            29



     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))
     115
     user=>



     (defn avg-age
      [coll]
      (/ (apply + (map :age coll)) (count coll)))




                                                                                        © 2009 Formos Software Development
Clojure: Data in Transformable Collections
       :first-name    Howard                 :first-name    Scott               :first-name        Molly


 {     :last-name   Lewis Ship
                                 } {         :last-name   Simon
                                                                   }{         :last-name      Newman
                                                                                                             }
          :age         42                         :age     44                    :age            29



     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))
     115
     user=>



     (defn avg-age
      [coll]
      (/ (apply + (map :age coll)) (count coll)))


     (defn avg                                                    (defn avg-age
      [f coll]                                                     [coll]
      (/ (apply + (map f coll))) (count coll)))                    (avg :age coll))



                                                                                           © 2009 Formos Software Development
Clojure: Data in Transformable Collections
       :first-name    Howard                 :first-name          Scott               :first-name        Molly


 {     :last-name   Lewis Ship
                                 } {         :last-name         Simon
                                                                         }{         :last-name      Newman
                                                                                                                   }
          :age         42                         :age           44                    :age            29



     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))
     115
     user=>



     (defn avg-age
      [coll]
      (/ (apply + (map :age coll)) (count coll)))


     (defn avg                                                          (defn avg-age
      [f coll]                                                           [coll]
      (/ (apply + (map f coll))) (count coll)))                          (avg :age coll))

                                                         (avg #(count (:last-name %)) persons)
                                                                                                 © 2009 Formos Software Development
© 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
                             © 2009 Formos Software Development
Clojure Concurrency

                      © 2009 Formos Software Development
Solving Deadlocks:
Timeout & Retry




                     © 2009 Formos Software Development
Solving
Deadlocks:
Specific Lock
Order



               © 2009 Formos Software Development
Solving Deadlocks:
Coarse Locks




Image © 2008 Marcin Wichary
http://flickr.com/photos/mwichary/2222776430/   © 2009 Formos Software Development
Locks are
                                              the Enemy
Image © 2007 James Manners
http://flickr.com/photos/jmanners/443421045/          © 2009 Formos Software Development
Clojure: Software Transactional Memory

(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.)



                        - 500.      + 500.     - 300.      + 300.



 Checking      1000.         500.                                                                          500.


 Savings       2000.                   2500.                  2800.                                       2800.


   MM          7000.                               6700.                                                  6700.

                                                                                   © 2009 Formos Software Development
Retries: Transactions Are Speculative

(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.)

                                                   + 300.

                        - 500.      - 300.      + 500.                        - 300.       + 300.



 Checking      1000.         500.
                                                              X                                                500.


 Savings       2000.                               2500.      2300.   2500.                      2800.        2800.


   MM          7000.                    6700.                         7000.                                   6700.
                                                                                  6700.

                                                                                       © 2009 Formos Software Development
© 2009 Formos Software Development
No
Blocking
       © 2009 Formos Software Development
© 2009 Formos Software Development
No Locks
       © 2009 Formos Software Development
© 2009 Formos Software Development
Persistent
Collections
         © 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?




Image © 2008 Daniel Chan
http://flickr.com/photos/chanchan222/2847443980/         © 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/queue
      user=> @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=>


                                                                     © 2009 Formos Software Development
Vars — Per-Thread Mutables
• (def) sets global binding


• (binding) to set up a per-thread override
                                                    Image © 2005 Jack Keene
                                                    http://www.flickr.com/photos/whatknot/3118124/


• (set!) if per-thread binding

     user=> (def x 1)
     #=(var user/x)
     user=> x
     1
     user=> (defn manipulate-x []
           (binding [x 2]
             (printf "Local x is %d" x)
             (set! x 3)
             (printf "nLocal x is now %dn" x)))
     #=(var user/manipulate-x)
     user=> (.run (Thread. manipulate-x))
     Local x is 2
     Local x is now 3
     nil
     user=> x
     1
                                                                     © 2009 Formos Software Development
Interfacing with Java APIs

 (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*)))




                                                                © 2009 Formos Software Development
Everything's a Var!




                                              Function


      Namespace                         Var      Value


                                                     ...
                  Symbol such as x or
                  map




                                              © 2009 Formos Software Development
Functions are stored in Vars



   user=> (defn say-hello [] (println "Hello"))
   #'user/say-hello
   user=> (say-hello)
   Hello
   nil
   user=> (binding [say-hello #(println "Goodbye")] (say-hello))
   Goodbye
   nil
   user=> (say-hello)
   Hello
   nil
   user=>




                                                                   © 2009 Formos Software Development
Agents — Single Thread Writes


user=> (def savings (agent 1000.))
#=(var user/savings)
user=> (def checking (agent 2000.))
#=(var user/checking)
user=> @savings
1000
user=> @checking
2000
user=> (send savings - 300.)
#<clojure.lang.Agent@c3233b>
user=> (send checking + 300.)
#<clojure.lang.Agent@67e5a7>
user=> @savings
700
user=> @checking
2300                         •Asynchonous
                           •Single threaded
                           •Non-transactional



                                                © 2009 Formos Software Development
Refs — Software Transactional Memory
  (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.)

     user=> @checking
     2000
     user=> @savings
     1000
     user=> (transfer checking savings 500.)
     1500
     user=> @checking
     1500
     user=> @savings
     1500
     user=> (ref-set savings 2000.)
     java.lang.IllegalStateException: No transaction running (NO_SOURCE_FILE:0)



                                                                                    © 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




                                                  © 2009 Formos Software Development
© 2009 Formos Software Development
❝The key to performance is elegance,
not battalions of special cases.❞




Jon Bentley and Doug McIlroy
                               © 2009 Formos Software Development
Wrap Up

          © 2009 Formos Software Development
Clojure
• 1.0 release: May 4 2009


• Simple, regular syntax


• Improves on Lisp: vectors, maps, sets


• Fully integrates with Java
                                                http://www.clojure.org
• Impressive functional & concurrency support


• Many features not covered here




                                                           © 2009 Formos Software Development
Stuart Halloway

                             Pragmatic Bookshelf




http://pragprog.com/titles/shcloj/programming-clojure
                                           © 2009 Formos Software Development
http://jnb.ociweb.com/jnb/jnbMar2009.html




                                   © 2009 Formos Software Development
Object Oriented




Copyright © A. Lipson 2003                           Copyright © 2007 Alan Chia
http://www.andrewlipson.com/escher/relativity.html   http://flickr.com/photos/seven13avenue/2080281038/   © 2009 Formos Software Development
Object Oriented




Copyright © A. Lipson 2003                           Copyright © 2007 Alan Chia
http://www.andrewlipson.com/escher/relativity.html   http://flickr.com/photos/seven13avenue/2080281038/   © 2009 Formos Software Development
Functional




             © 2009 Formos Software Development
Functional




Image © 2007 Woodley Wonderworks
http://flickr.com/photos/wwworks/2222523486/   © 2009 Formos Software Development

More Related Content

What's hot

CodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical GroovyCodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical GroovyCodecamp Romania
 
Design patterns in javascript
Design patterns in javascriptDesign patterns in javascript
Design patterns in javascriptMiao Siyu
 
Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)
Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)
Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)Howard Lewis Ship
 
Implementing a many-to-many Relationship with Slick
Implementing a many-to-many Relationship with SlickImplementing a many-to-many Relationship with Slick
Implementing a many-to-many Relationship with SlickHermann Hueck
 
JavaFX Your Way: Building JavaFX Applications with Alternative Languages
JavaFX Your Way: Building JavaFX Applications with Alternative LanguagesJavaFX Your Way: Building JavaFX Applications with Alternative Languages
JavaFX Your Way: Building JavaFX Applications with Alternative LanguagesStephen Chin
 
Programming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
Programming Java - Lection 07 - Puzzlers - Lavrentyev FedorProgramming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
Programming Java - Lection 07 - Puzzlers - Lavrentyev FedorFedor Lavrentyev
 
Beyond Breakpoints: Advanced Debugging with XCode
Beyond Breakpoints: Advanced Debugging with XCodeBeyond Breakpoints: Advanced Debugging with XCode
Beyond Breakpoints: Advanced Debugging with XCodeAijaz Ansari
 
LetSwift RxSwift 시작하기
LetSwift RxSwift 시작하기LetSwift RxSwift 시작하기
LetSwift RxSwift 시작하기Wanbok Choi
 
Hibernate
Hibernate Hibernate
Hibernate Sunil OS
 
Planet-HTML5-Game-Engine Javascript Performance Enhancement
Planet-HTML5-Game-Engine Javascript Performance EnhancementPlanet-HTML5-Game-Engine Javascript Performance Enhancement
Planet-HTML5-Game-Engine Javascript Performance Enhancementup2soul
 
Swift internals
Swift internalsSwift internals
Swift internalsJung Kim
 
Fantastic DSL in Python
Fantastic DSL in PythonFantastic DSL in Python
Fantastic DSL in Pythonkwatch
 
Examples from Pune meetup
Examples from Pune meetupExamples from Pune meetup
Examples from Pune meetupSantosh Ojha
 
ScalaDays 2014 - Reactive Scala 3D Game Engine
ScalaDays 2014 - Reactive Scala 3D Game Engine ScalaDays 2014 - Reactive Scala 3D Game Engine
ScalaDays 2014 - Reactive Scala 3D Game Engine Aleksandar Prokopec
 
Introducción rápida a SQL
Introducción rápida a SQLIntroducción rápida a SQL
Introducción rápida a SQLCarlos Hernando
 
Marimba - Ein MapReduce-basiertes Programmiermodell für selbstwartbare Aggreg...
Marimba - Ein MapReduce-basiertes Programmiermodell für selbstwartbare Aggreg...Marimba - Ein MapReduce-basiertes Programmiermodell für selbstwartbare Aggreg...
Marimba - Ein MapReduce-basiertes Programmiermodell für selbstwartbare Aggreg...Johannes Schildgen
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Jeff Carouth
 
groovy databases
groovy databasesgroovy databases
groovy databasesPaul King
 
Advanced Java Practical File
Advanced Java Practical FileAdvanced Java Practical File
Advanced Java Practical FileSoumya Behera
 

What's hot (20)

CodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical GroovyCodeCamp Iasi 10 march 2012 - Practical Groovy
CodeCamp Iasi 10 march 2012 - Practical Groovy
 
Design patterns in javascript
Design patterns in javascriptDesign patterns in javascript
Design patterns in javascript
 
Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)
Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)
Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)
 
CoffeeScript
CoffeeScriptCoffeeScript
CoffeeScript
 
Implementing a many-to-many Relationship with Slick
Implementing a many-to-many Relationship with SlickImplementing a many-to-many Relationship with Slick
Implementing a many-to-many Relationship with Slick
 
JavaFX Your Way: Building JavaFX Applications with Alternative Languages
JavaFX Your Way: Building JavaFX Applications with Alternative LanguagesJavaFX Your Way: Building JavaFX Applications with Alternative Languages
JavaFX Your Way: Building JavaFX Applications with Alternative Languages
 
Programming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
Programming Java - Lection 07 - Puzzlers - Lavrentyev FedorProgramming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
Programming Java - Lection 07 - Puzzlers - Lavrentyev Fedor
 
Beyond Breakpoints: Advanced Debugging with XCode
Beyond Breakpoints: Advanced Debugging with XCodeBeyond Breakpoints: Advanced Debugging with XCode
Beyond Breakpoints: Advanced Debugging with XCode
 
LetSwift RxSwift 시작하기
LetSwift RxSwift 시작하기LetSwift RxSwift 시작하기
LetSwift RxSwift 시작하기
 
Hibernate
Hibernate Hibernate
Hibernate
 
Planet-HTML5-Game-Engine Javascript Performance Enhancement
Planet-HTML5-Game-Engine Javascript Performance EnhancementPlanet-HTML5-Game-Engine Javascript Performance Enhancement
Planet-HTML5-Game-Engine Javascript Performance Enhancement
 
Swift internals
Swift internalsSwift internals
Swift internals
 
Fantastic DSL in Python
Fantastic DSL in PythonFantastic DSL in Python
Fantastic DSL in Python
 
Examples from Pune meetup
Examples from Pune meetupExamples from Pune meetup
Examples from Pune meetup
 
ScalaDays 2014 - Reactive Scala 3D Game Engine
ScalaDays 2014 - Reactive Scala 3D Game Engine ScalaDays 2014 - Reactive Scala 3D Game Engine
ScalaDays 2014 - Reactive Scala 3D Game Engine
 
Introducción rápida a SQL
Introducción rápida a SQLIntroducción rápida a SQL
Introducción rápida a SQL
 
Marimba - Ein MapReduce-basiertes Programmiermodell für selbstwartbare Aggreg...
Marimba - Ein MapReduce-basiertes Programmiermodell für selbstwartbare Aggreg...Marimba - Ein MapReduce-basiertes Programmiermodell für selbstwartbare Aggreg...
Marimba - Ein MapReduce-basiertes Programmiermodell für selbstwartbare Aggreg...
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4
 
groovy databases
groovy databasesgroovy databases
groovy databases
 
Advanced Java Practical File
Advanced Java Practical FileAdvanced Java Practical File
Advanced Java Practical File
 

Viewers also liked

Doing data science with Clojure
Doing data science with ClojureDoing data science with Clojure
Doing data science with ClojureSimon Belak
 
20 reasons why we don't need architects (@pavlobaron)
20 reasons why we don't need architects (@pavlobaron)20 reasons why we don't need architects (@pavlobaron)
20 reasons why we don't need architects (@pavlobaron)Pavlo Baron
 
Winning the Erlang Edit•Build•Test Cycle
Winning the Erlang Edit•Build•Test CycleWinning the Erlang Edit•Build•Test Cycle
Winning the Erlang Edit•Build•Test CycleRusty Klophaus
 
Erlang - Because s**t Happens by Mahesh Paolini-Subramanya
Erlang - Because s**t Happens by Mahesh Paolini-SubramanyaErlang - Because s**t Happens by Mahesh Paolini-Subramanya
Erlang - Because s**t Happens by Mahesh Paolini-SubramanyaHakka Labs
 
What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)Pavlo Baron
 
Messaging With Erlang And Jabber
Messaging With  Erlang And  JabberMessaging With  Erlang And  Jabber
Messaging With Erlang And Jabberl xf
 
Clojure made-simple - John Stevenson
Clojure made-simple - John StevensonClojure made-simple - John Stevenson
Clojure made-simple - John StevensonJAX London
 
NDC London 2014: Erlang Patterns Matching Business Needs
NDC London 2014: Erlang Patterns Matching Business NeedsNDC London 2014: Erlang Patterns Matching Business Needs
NDC London 2014: Erlang Patterns Matching Business NeedsTorben Hoffmann
 
VoltDB and Erlang - Tech planet 2012
VoltDB and Erlang - Tech planet 2012VoltDB and Erlang - Tech planet 2012
VoltDB and Erlang - Tech planet 2012Eonblast
 
Introduction to Erlang for Python Programmers
Introduction to Erlang for Python ProgrammersIntroduction to Erlang for Python Programmers
Introduction to Erlang for Python ProgrammersPython Ireland
 
Clojure Intro
Clojure IntroClojure Intro
Clojure Introthnetos
 
Elixir for aspiring Erlang developers
Elixir for aspiring Erlang developersElixir for aspiring Erlang developers
Elixir for aspiring Erlang developersTorben Dohrn
 
Clojure, Plain and Simple
Clojure, Plain and SimpleClojure, Plain and Simple
Clojure, Plain and SimpleBen Mabey
 
Elixir Into Production
Elixir Into ProductionElixir Into Production
Elixir Into ProductionJamie Winsor
 

Viewers also liked (20)

Doing data science with Clojure
Doing data science with ClojureDoing data science with Clojure
Doing data science with Clojure
 
20 reasons why we don't need architects (@pavlobaron)
20 reasons why we don't need architects (@pavlobaron)20 reasons why we don't need architects (@pavlobaron)
20 reasons why we don't need architects (@pavlobaron)
 
Clojure class
Clojure classClojure class
Clojure class
 
High Performance Erlang
High  Performance  ErlangHigh  Performance  Erlang
High Performance Erlang
 
Winning the Erlang Edit•Build•Test Cycle
Winning the Erlang Edit•Build•Test CycleWinning the Erlang Edit•Build•Test Cycle
Winning the Erlang Edit•Build•Test Cycle
 
Erlang - Because s**t Happens by Mahesh Paolini-Subramanya
Erlang - Because s**t Happens by Mahesh Paolini-SubramanyaErlang - Because s**t Happens by Mahesh Paolini-Subramanya
Erlang - Because s**t Happens by Mahesh Paolini-Subramanya
 
What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)
 
Messaging With Erlang And Jabber
Messaging With  Erlang And  JabberMessaging With  Erlang And  Jabber
Messaging With Erlang And Jabber
 
Elixir talk
Elixir talkElixir talk
Elixir talk
 
Clojure values
Clojure valuesClojure values
Clojure values
 
Clojure made-simple - John Stevenson
Clojure made-simple - John StevensonClojure made-simple - John Stevenson
Clojure made-simple - John Stevenson
 
From Perl To Elixir
From Perl To ElixirFrom Perl To Elixir
From Perl To Elixir
 
NDC London 2014: Erlang Patterns Matching Business Needs
NDC London 2014: Erlang Patterns Matching Business NeedsNDC London 2014: Erlang Patterns Matching Business Needs
NDC London 2014: Erlang Patterns Matching Business Needs
 
VoltDB and Erlang - Tech planet 2012
VoltDB and Erlang - Tech planet 2012VoltDB and Erlang - Tech planet 2012
VoltDB and Erlang - Tech planet 2012
 
Introduction to Erlang for Python Programmers
Introduction to Erlang for Python ProgrammersIntroduction to Erlang for Python Programmers
Introduction to Erlang for Python Programmers
 
Clojure Intro
Clojure IntroClojure Intro
Clojure Intro
 
Elixir for aspiring Erlang developers
Elixir for aspiring Erlang developersElixir for aspiring Erlang developers
Elixir for aspiring Erlang developers
 
Clojure, Plain and Simple
Clojure, Plain and SimpleClojure, Plain and Simple
Clojure, Plain and Simple
 
Elixir Into Production
Elixir Into ProductionElixir Into Production
Elixir Into Production
 
Erlang - Because S**t Happens
Erlang - Because S**t HappensErlang - Because S**t Happens
Erlang - Because S**t Happens
 

Similar to Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)

From Java To Clojure (English version)
From Java To Clojure (English version)From Java To Clojure (English version)
From Java To Clojure (English version)Kent Ohashi
 
Elixir & Phoenix - fast, concurrent and explicit
Elixir & Phoenix - fast, concurrent and explicitElixir & Phoenix - fast, concurrent and explicit
Elixir & Phoenix - fast, concurrent and explicitTobias Pfeiffer
 
Clojure - A new Lisp
Clojure - A new LispClojure - A new Lisp
Clojure - A new Lispelliando dias
 
2011 py con
2011 py con2011 py con
2011 py conEing Ong
 
ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015Michiel Borkent
 
Exploring Clojurescript
Exploring ClojurescriptExploring Clojurescript
Exploring ClojurescriptLuke Donnet
 
GR8Conf 2009: What's New in Groovy 1.6? by Guillaume Laforge
GR8Conf 2009: What's New in Groovy 1.6? by Guillaume LaforgeGR8Conf 2009: What's New in Groovy 1.6? by Guillaume Laforge
GR8Conf 2009: What's New in Groovy 1.6? by Guillaume LaforgeGR8Conf
 
Clojure and Modularity
Clojure and ModularityClojure and Modularity
Clojure and Modularityelliando dias
 
Clojure Interoperability
Clojure InteroperabilityClojure Interoperability
Clojure Interoperabilityrik0
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing UpDavid Padbury
 
2010 bb dev con
2010 bb dev con 2010 bb dev con
2010 bb dev con Eing Ong
 
Why Every Tester Should Learn Ruby
Why Every Tester Should Learn RubyWhy Every Tester Should Learn Ruby
Why Every Tester Should Learn RubyRaimonds Simanovskis
 
Re-Design with Elixir/OTP
Re-Design with Elixir/OTPRe-Design with Elixir/OTP
Re-Design with Elixir/OTPMustafa TURAN
 
Advanced Python, Part 1
Advanced Python, Part 1Advanced Python, Part 1
Advanced Python, Part 1Zaar Hai
 
Phoenix for laravel developers
Phoenix for laravel developersPhoenix for laravel developers
Phoenix for laravel developersLuiz Messias
 
Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Guillaume Laforge
 

Similar to Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge) (20)

Codemash-Clojure.pdf
Codemash-Clojure.pdfCodemash-Clojure.pdf
Codemash-Clojure.pdf
 
From Java To Clojure (English version)
From Java To Clojure (English version)From Java To Clojure (English version)
From Java To Clojure (English version)
 
Elixir & Phoenix - fast, concurrent and explicit
Elixir & Phoenix - fast, concurrent and explicitElixir & Phoenix - fast, concurrent and explicit
Elixir & Phoenix - fast, concurrent and explicit
 
Clojure - A new Lisp
Clojure - A new LispClojure - A new Lisp
Clojure - A new Lisp
 
2011 py con
2011 py con2011 py con
2011 py con
 
Clojure And Swing
Clojure And SwingClojure And Swing
Clojure And Swing
 
ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015
 
Exploring Clojurescript
Exploring ClojurescriptExploring Clojurescript
Exploring Clojurescript
 
GR8Conf 2009: What's New in Groovy 1.6? by Guillaume Laforge
GR8Conf 2009: What's New in Groovy 1.6? by Guillaume LaforgeGR8Conf 2009: What's New in Groovy 1.6? by Guillaume Laforge
GR8Conf 2009: What's New in Groovy 1.6? by Guillaume Laforge
 
Clojure and Modularity
Clojure and ModularityClojure and Modularity
Clojure and Modularity
 
Clojure Interoperability
Clojure InteroperabilityClojure Interoperability
Clojure Interoperability
 
JavaScript Growing Up
JavaScript Growing UpJavaScript Growing Up
JavaScript Growing Up
 
2010 bb dev con
2010 bb dev con 2010 bb dev con
2010 bb dev con
 
Introduction to Groovy
Introduction to GroovyIntroduction to Groovy
Introduction to Groovy
 
Why Every Tester Should Learn Ruby
Why Every Tester Should Learn RubyWhy Every Tester Should Learn Ruby
Why Every Tester Should Learn Ruby
 
Re-Design with Elixir/OTP
Re-Design with Elixir/OTPRe-Design with Elixir/OTP
Re-Design with Elixir/OTP
 
Advanced Python, Part 1
Advanced Python, Part 1Advanced Python, Part 1
Advanced Python, Part 1
 
Modern frontend in react.js
Modern frontend in react.jsModern frontend in react.js
Modern frontend in react.js
 
Phoenix for laravel developers
Phoenix for laravel developersPhoenix for laravel developers
Phoenix for laravel developers
 
Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008Groovy Introduction - JAX Germany - 2008
Groovy Introduction - JAX Germany - 2008
 

More from Howard Lewis Ship

Testing Web Applications with GEB
Testing Web Applications with GEBTesting Web Applications with GEB
Testing Web Applications with GEBHoward Lewis Ship
 
Spock: A Highly Logical Way To Test
Spock: A Highly Logical Way To TestSpock: A Highly Logical Way To Test
Spock: A Highly Logical Way To TestHoward Lewis Ship
 
Backbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserBackbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserHoward Lewis Ship
 
Modern Application Foundations: Underscore and Twitter Bootstrap
Modern Application Foundations: Underscore and Twitter BootstrapModern Application Foundations: Underscore and Twitter Bootstrap
Modern Application Foundations: Underscore and Twitter BootstrapHoward Lewis Ship
 
Have Your Cake and Eat It Too: Meta-Programming Techniques for Java
Have Your Cake and Eat It Too: Meta-Programming Techniques for JavaHave Your Cake and Eat It Too: Meta-Programming Techniques for Java
Have Your Cake and Eat It Too: Meta-Programming Techniques for JavaHoward Lewis Ship
 
Arduino: Open Source Hardware Hacking from the Software Nerd Perspective
Arduino: Open Source Hardware Hacking from the Software Nerd PerspectiveArduino: Open Source Hardware Hacking from the Software Nerd Perspective
Arduino: Open Source Hardware Hacking from the Software Nerd PerspectiveHoward Lewis Ship
 
Practical Clojure Programming
Practical Clojure ProgrammingPractical Clojure Programming
Practical Clojure ProgrammingHoward Lewis Ship
 
Tapestry 5: Java Power, Scripting Ease
Tapestry 5: Java Power, Scripting EaseTapestry 5: Java Power, Scripting Ease
Tapestry 5: Java Power, Scripting EaseHoward Lewis Ship
 
Brew up a Rich Web Application with Cappuccino
Brew up a Rich Web Application with CappuccinoBrew up a Rich Web Application with Cappuccino
Brew up a Rich Web Application with CappuccinoHoward Lewis Ship
 
Tapestry: State of the Union
Tapestry: State of the UnionTapestry: State of the Union
Tapestry: State of the UnionHoward Lewis Ship
 

More from Howard Lewis Ship (13)

Testing Web Applications with GEB
Testing Web Applications with GEBTesting Web Applications with GEB
Testing Web Applications with GEB
 
Spock: A Highly Logical Way To Test
Spock: A Highly Logical Way To TestSpock: A Highly Logical Way To Test
Spock: A Highly Logical Way To Test
 
Backbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The BrowserBackbone.js: Run your Application Inside The Browser
Backbone.js: Run your Application Inside The Browser
 
Modern Application Foundations: Underscore and Twitter Bootstrap
Modern Application Foundations: Underscore and Twitter BootstrapModern Application Foundations: Underscore and Twitter Bootstrap
Modern Application Foundations: Underscore and Twitter Bootstrap
 
Have Your Cake and Eat It Too: Meta-Programming Techniques for Java
Have Your Cake and Eat It Too: Meta-Programming Techniques for JavaHave Your Cake and Eat It Too: Meta-Programming Techniques for Java
Have Your Cake and Eat It Too: Meta-Programming Techniques for Java
 
Arduino: Open Source Hardware Hacking from the Software Nerd Perspective
Arduino: Open Source Hardware Hacking from the Software Nerd PerspectiveArduino: Open Source Hardware Hacking from the Software Nerd Perspective
Arduino: Open Source Hardware Hacking from the Software Nerd Perspective
 
Practical Clojure Programming
Practical Clojure ProgrammingPractical Clojure Programming
Practical Clojure Programming
 
Codemash-Tapestry.pdf
Codemash-Tapestry.pdfCodemash-Tapestry.pdf
Codemash-Tapestry.pdf
 
Tapestry 5: Java Power, Scripting Ease
Tapestry 5: Java Power, Scripting EaseTapestry 5: Java Power, Scripting Ease
Tapestry 5: Java Power, Scripting Ease
 
Brew up a Rich Web Application with Cappuccino
Brew up a Rich Web Application with CappuccinoBrew up a Rich Web Application with Cappuccino
Brew up a Rich Web Application with Cappuccino
 
Clojure Deep Dive
Clojure Deep DiveClojure Deep Dive
Clojure Deep Dive
 
Cascade
CascadeCascade
Cascade
 
Tapestry: State of the Union
Tapestry: State of the UnionTapestry: State of the Union
Tapestry: State of the Union
 

Recently uploaded

Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditSkynet Technologies
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...AliaaTarek5
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Scott Andery
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterMydbops
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesThousandEyes
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...panagenda
 

Recently uploaded (20)

Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance Audit
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL Router
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
 
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
 

Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)

  • 1. Clojure: Functional Concurrency for the JVM Howard M. Lewis Ship Director of Open Source Technology Formos Software Development howard.lewis.ship@formos.com © 2009 Formos Software Development
  • 2. Clojure: The Language © 2009 Formos Software Development
  • 3. http://xkcd.com/297/ Clojure: The Language © 2009 Formos Software Development
  • 4. Rich Hickey © 2009 Formos Software Development
  • 5. Code is Data Quoted list of '(1 2 3) numbers (biggest 5 42) Function call Function definition (defn biggest "Find the maximum of two numbers" [x y] (if (> x y) x y)) © 2009 Formos Software Development
  • 6. 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) 42 user=> (doc biggest) ------------------------- user/biggest ([x y]) Find the maximum of two numbers nil user=> '(1 2 3) (1 2 3) user=> '(biggest 5 42) (biggest 5 42) user=> (first '(biggest 5 42)) biggest user=> (eval '(biggest 5 42)) 42 © 2009 Formos Software Development
  • 7. There Is No Interpreter Source Code Repl Input Clojure User Classes Java Evaluator Compiler Clojure Source Files Java Libraries JVM Operating System © 2009 Formos Software Development
  • 8. Clojure Literals user=> 42 42 user=> "A Clojure String" "A Clojure String" user=> nil nil user=> :balance :balance user=> true true user=> false false © 2009 Formos Software Development
  • 9. Clojure Literals user=> 5 5 user=> 5.001 5.001 user=> 22/7 22/7 user=> (* 2 22/7) 44/7 user=> (* 100000 100000 100000) 1000000000000000 user=> (+ 5. 0.000000000000000001) 5.0 user=> (+ 5.0M 0.000000000000000001M) 5.000000000000000001M © 2009 Formos Software Development
  • 10. Java Interop factory.setNamespaceAware(true) (.setNamespaceAware factory true) new StringBuffer() (new StringBuffer) (StringBuffer.) factory.newSAXParser().parse(src, handler) (.. factory newSAXParser (parse src handler)) MyObject.ivar = "foo"; (set! (. MyObject ivar) "foo") © 2009 Formos Software Development
  • 11. Java Interop frame.add(panel, BorderLayout.CENTER); frame.add(greetButton, BorderLayout.SOUTH); frame.pack(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); (doto frame (.add panel BorderLayout/CENTER) (.add greet-button BorderLayout/SOUTH) (.pack) (.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE) (.setVisible true)) © 2009 Formos Software Development
  • 12. Clojure Collections: Lists lst user=> (def lst `(1 2 3)) #=(var user/lst) user=> lst (1 2 3) user=> (first lst) 1 1 user=> (rest lst) (2 3) user=> (conj lst 4) 2 (4 1 2 3) user=> (cons 4 lst) (4 1 2 3) 3 © 2009 Formos Software Development
  • 13. Clojure Collections: Lists 4 lst user=> (def lst `(1 2 3)) #=(var user/lst) user=> lst (1 2 3) user=> (first lst) 1 1 user=> (rest lst) (2 3) user=> (conj lst 4) 2 (4 1 2 3) user=> (cons 4 lst) (4 1 2 3) 3 © 2009 Formos Software Development
  • 14. Clojure Collections: Vectors user=> (def v [:moe :larry :curly]) #=(var user/v) user=> v [:moe :larry :curly] user=> (first v) :moe user=> (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 © 2009 Formos Software Development
  • 15. 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" map is a user=> (m :last-name) function of "Lewis Ship" its keys 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 Keywords are functions, too! © 2009 Formos Software Development
  • 16. Clojure Collections: Sets user=> (def s #{"Howard" "Suzanne" "Molly" "Jim"}) #=(var user/s) user=> s #{"Howard" "Jim" "Molly" "Suzanne"} user=> (contains? s "Howard") true user=> (contains? s "howard") false set is a user=> (s "Howard") function of "Howard" its elements user=> (s "Rhys") nil user=> (conj s "Howard") #{"Howard" "Jim" "Molly" "Suzanne"} user=> (conj s "Scott") #{"Howard" "Jim" "Molly" "Suzanne" "Scott"} © 2009 Formos Software Development
  • 17. © 2009 Formos Software Development
  • 18. ❝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 © 2009 Formos Software Development
  • 19. Functional Programming © 2009 Formos Software Development
  • 20. Functional Programming © 2009 Formos Software Development
  • 21. © 2009 Formos Software Development
  • 22. No Mutable State© 2009 Formos Software Development
  • 23. © 2009 Formos Software Development
  • 24. No Side Effects © 2009 Formos Software Development
  • 25. © 2009 Formos Software Development
  • 26. First Class Functions © 2009 Formos Software Development
  • 27. © 2009 Formos Software Development
  • 28. Functional Composition © 2009 Formos Software Development
  • 29. 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); } Outer function controls the SwingUtilities.invokeLater(new Runnable() context: { public void run() • Thread { • Exception handling progressBar.setValue(progressBar.getValue() + 1); } • Parameters }); © 2009 Formos Software Development
  • 30. Functional Java Collections public interface Predicate<T> { boolean accept(T value); } 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; } return CollectionUtils.filter(new Predicate<String>() { public boolean accept(String value) { return !value.startsWith("."); } }, names); © 2009 Formos Software Development
  • 31. Functional Clojure Collections Function Anonymous parameter function (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=> © 2009 Formos Software Development
  • 32. First Class Functions (filter #(not (.startsWith % ".")) names) function as parameter to function (defn require-extension [ext] (fn [file-name] (= ext (last (split-string file-name "."))))) function as return value (defn filter-by-extension [ext coll] (filter (require-extension ext) coll)) composing functions © 2009 Formos Software Development
  • 33. Bridging Java and Clojure SwingUtilities.invokeLater(new Runnable() { public void run() { progressBar.setValue(progressBar.getValue() + 1); } }); Invoke static method (SwingUtilities/invokeLater #(.setValue progressBar (inc (.getValue progressBar)))) Clojure functions implement: • Runnable • Callable • Comparator © 2009 Formos Software Development
  • 34. Life without the for loop public static int sum(int[] vals) { int total = 0; col for (int val : vals) total += val; return total; } x y (defn sum z [col] (reduce + 0 col)) ➠ 0 + col[0] + col[1] + col[2] ... © 2009 Formos Software Development
  • 35. Life without the for loop public static int sum(int[] vals) { int total = 0; col for (int val : vals) total += val; return total; } x y (defn sum z [col] (reduce + 0 col)) ➠ 0 + col[0] + col[1] + col[2] ... ➠ (+ 0 (first col)) (+ (+ 0 (first col)) (first (rest col))) (+ (+ (+ 0 (first col)) (first (rest col))) (first (rest (rest col)))) ... © 2009 Formos Software Development
  • 36. 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 f [col] (map #(format "%9.2f" %) col)) f Apply function to each item, forming f new seq user=> (format-doubles '(2.5 3.7 -22.7)) (" 2.50" " 3.70" " -22.70") © 2009 Formos Software Development
  • 37. 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=> (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]) © 2009 Formos Software Development
  • 38. 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=> (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]) (defn convert-attributes-to-tokens [attrs] (for [x (range (.getLength attrs))] (let [uri (.getURI attrs x) name (.getLocalName attrs x) value (.getValue attrs x) token (…) ] token))) © 2009 Formos Software Development
  • 39. Laziness is a Virtue Image © 2007 Jon Fife http://flickr.com/photos/good-karma/577632972/ © 2009 Formos Software Development
  • 40. 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) Image © 2007 Jon Fife http://flickr.com/photos/good-karma/577632972/ © 2009 Formos Software Development
  • 41. Laziness © 2009 Formos Software Development
  • 42. Java: Data Encapsulated in Objects Person Person Person Person firstName: "Howard" firstName: "Scott" firstName: "Molly" firstName: "David" lastName: "Lewis Ship" lastName: "Simon" lastName: "Newman" lastName: "Goldman" age: 42 age: 44 age: 29 age: 42 public double averageAge(Collection<Person> persons) { double total = 0.0; for (Person p : persons) total += p.getAge(); return total / persons.size(); } © 2009 Formos Software Development
  • 43. Clojure: Data in Transformable Collections :first-name Howard :first-name Scott :first-name Molly { :last-name Lewis Ship } { :last-name Simon }{ :last-name Newman } :age 42 :age 44 :age 29 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)) 115 user=> © 2009 Formos Software Development
  • 44. Clojure: Data in Transformable Collections :first-name Howard :first-name Scott :first-name Molly { :last-name Lewis Ship } { :last-name Simon }{ :last-name Newman } :age 42 :age 44 :age 29 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)) 115 user=> (defn avg-age [coll] (/ (apply + (map :age coll)) (count coll))) © 2009 Formos Software Development
  • 45. Clojure: Data in Transformable Collections :first-name Howard :first-name Scott :first-name Molly { :last-name Lewis Ship } { :last-name Simon }{ :last-name Newman } :age 42 :age 44 :age 29 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)) 115 user=> (defn avg-age [coll] (/ (apply + (map :age coll)) (count coll))) (defn avg (defn avg-age [f coll] [coll] (/ (apply + (map f coll))) (count coll))) (avg :age coll)) © 2009 Formos Software Development
  • 46. Clojure: Data in Transformable Collections :first-name Howard :first-name Scott :first-name Molly { :last-name Lewis Ship } { :last-name Simon }{ :last-name Newman } :age 42 :age 44 :age 29 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)) 115 user=> (defn avg-age [coll] (/ (apply + (map :age coll)) (count coll))) (defn avg (defn avg-age [f coll] [coll] (/ (apply + (map f coll))) (count coll))) (avg :age coll)) (avg #(count (:last-name %)) persons) © 2009 Formos Software Development
  • 47. © 2009 Formos Software Development
  • 48. ❝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 © 2009 Formos Software Development
  • 49. Clojure Concurrency © 2009 Formos Software Development
  • 50. Solving Deadlocks: Timeout & Retry © 2009 Formos Software Development
  • 51. Solving Deadlocks: Specific Lock Order © 2009 Formos Software Development
  • 52. Solving Deadlocks: Coarse Locks Image © 2008 Marcin Wichary http://flickr.com/photos/mwichary/2222776430/ © 2009 Formos Software Development
  • 53. Locks are the Enemy Image © 2007 James Manners http://flickr.com/photos/jmanners/443421045/ © 2009 Formos Software Development
  • 54. Clojure: Software Transactional Memory (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.) - 500. + 500. - 300. + 300. Checking 1000. 500. 500. Savings 2000. 2500. 2800. 2800. MM 7000. 6700. 6700. © 2009 Formos Software Development
  • 55. Retries: Transactions Are Speculative (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.) + 300. - 500. - 300. + 500. - 300. + 300. Checking 1000. 500. X 500. Savings 2000. 2500. 2300. 2500. 2800. 2800. MM 7000. 6700. 7000. 6700. 6700. © 2009 Formos Software Development
  • 56. © 2009 Formos Software Development
  • 57. No Blocking © 2009 Formos Software Development
  • 58. © 2009 Formos Software Development
  • 59. No Locks © 2009 Formos Software Development
  • 60. © 2009 Formos Software Development
  • 61. Persistent Collections © 2009 Formos Software Development
  • 62. Managing Mutation • What can change? • Reference types: atom, var, agent, ref • When can they change? • When are changes visible to other threads? Image © 2008 Daniel Chan http://flickr.com/photos/chanchan222/2847443980/ © 2009 Formos Software Development
  • 63. 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/queue user=> @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=> © 2009 Formos Software Development
  • 64. Vars — Per-Thread Mutables • (def) sets global binding • (binding) to set up a per-thread override Image © 2005 Jack Keene http://www.flickr.com/photos/whatknot/3118124/ • (set!) if per-thread binding user=> (def x 1) #=(var user/x) user=> x 1 user=> (defn manipulate-x [] (binding [x 2] (printf "Local x is %d" x) (set! x 3) (printf "nLocal x is now %dn" x))) #=(var user/manipulate-x) user=> (.run (Thread. manipulate-x)) Local x is 2 Local x is now 3 nil user=> x 1 © 2009 Formos Software Development
  • 65. Interfacing with Java APIs (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*))) © 2009 Formos Software Development
  • 66. Everything's a Var! Function Namespace Var Value ... Symbol such as x or map © 2009 Formos Software Development
  • 67. Functions are stored in Vars user=> (defn say-hello [] (println "Hello")) #'user/say-hello user=> (say-hello) Hello nil user=> (binding [say-hello #(println "Goodbye")] (say-hello)) Goodbye nil user=> (say-hello) Hello nil user=> © 2009 Formos Software Development
  • 68. Agents — Single Thread Writes user=> (def savings (agent 1000.)) #=(var user/savings) user=> (def checking (agent 2000.)) #=(var user/checking) user=> @savings 1000 user=> @checking 2000 user=> (send savings - 300.) #<clojure.lang.Agent@c3233b> user=> (send checking + 300.) #<clojure.lang.Agent@67e5a7> user=> @savings 700 user=> @checking 2300 •Asynchonous •Single threaded •Non-transactional © 2009 Formos Software Development
  • 69. Refs — Software Transactional Memory (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.) user=> @checking 2000 user=> @savings 1000 user=> (transfer checking savings 500.) 1500 user=> @checking 1500 user=> @savings 1500 user=> (ref-set savings 2000.) java.lang.IllegalStateException: No transaction running (NO_SOURCE_FILE:0) © 2009 Formos Software Development
  • 70. 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 © 2009 Formos Software Development
  • 71. © 2009 Formos Software Development
  • 72. ❝The key to performance is elegance, not battalions of special cases.❞ Jon Bentley and Doug McIlroy © 2009 Formos Software Development
  • 73. Wrap Up © 2009 Formos Software Development
  • 74. Clojure • 1.0 release: May 4 2009 • Simple, regular syntax • Improves on Lisp: vectors, maps, sets • Fully integrates with Java http://www.clojure.org • Impressive functional & concurrency support • Many features not covered here © 2009 Formos Software Development
  • 75. Stuart Halloway Pragmatic Bookshelf http://pragprog.com/titles/shcloj/programming-clojure © 2009 Formos Software Development
  • 76. http://jnb.ociweb.com/jnb/jnbMar2009.html © 2009 Formos Software Development
  • 77. Object Oriented Copyright © A. Lipson 2003 Copyright © 2007 Alan Chia http://www.andrewlipson.com/escher/relativity.html http://flickr.com/photos/seven13avenue/2080281038/ © 2009 Formos Software Development
  • 78. Object Oriented Copyright © A. Lipson 2003 Copyright © 2007 Alan Chia http://www.andrewlipson.com/escher/relativity.html http://flickr.com/photos/seven13avenue/2080281038/ © 2009 Formos Software Development
  • 79. Functional © 2009 Formos Software Development
  • 80. Functional Image © 2007 Woodley Wonderworks http://flickr.com/photos/wwworks/2222523486/ © 2009 Formos Software Development