SlideShare una empresa de Scribd logo
1 de 71
Descargar para leer sin conexión
Clojure:
Functional
Concurrency for
the JVM
Howard M. Lewis Ship
TWD Consulting
hlship@gmail.com
                1      © 2010 Howard Lewis Ship
Clojure: Why
Functional
Programming
Matters
Howard M. Lewis Ship
TWD Consulting
hlship@gmail.com
                2      © 2010 Howard Lewis Ship
Clojure: Towards
the Essence of
Programming
Howard M. Lewis Ship
TWD Consulting
hlship@gmail.com
                3      © 2010 Howard Lewis Ship
essence
noun
the intrinsic nature or indispensable quality of
something, esp. something abstract, that
determines its character : conflict is the essence of
drama.




                          4                      © 2010 Howard Lewis Ship
Mainstream Programming

         Applications

         Frameworks

           Libraries

          Language

       Operating System



              5           © 2010 Howard Lewis Ship
Ceremony
   vs.
 Essence
   6   © 2010 Howard Lewis Ship
Is your language ...




                7      © 2010 Howard Lewis Ship
… holding
    you back?
8        © 2010 Howard Lewis Ship
Java: Data Encapsulated in Objects
           Stock                  Stock                    Stock
        ticker: AAPL           ticker: MSFT            ticker: ORCL
     lastTrade: 203.25       lastTrade: 29.12        lastTrade: 21.90
       open: 204.50             open: 29.08             open: 21.83
         shares: 100             shares: 50              shares: 200



     public static void sortByLastTrade(List<Stock> portfolio)
     {
        Comparator<Stock> c = new Comparator<Stock>()
        {
           public int compare(Stock o1, Stock o2)
           {
              public static void sortByOpen(List<Stock> portfolio)
              return o1.getLastTrade() - o2.getLastTrade();
              {
           }
                 Comparator<Stock> c = new Comparator<Stock>()
        };
                 {
                    public int compare(Stock o1, Stock o2)
        Collections.sort(portfolio, c);
                    {
     }
                       return o1.getOpen() - o2.getOpen();
                    }
                 };

                   Collections.sort(portfolio, c);
               }


                                   9                                    © 2010 Howard Lewis Ship
Clojure: Data in Maps and Lists
       :ticker     AAPL             :ticker        MSFT           :ticker     ORCL


     :last-trade   203.25         :last-trade      29.12        :last-trade   21.90

 {     :open       204.50   } {     :open          29.08   }{     :open       21.83       }
      :shares       100            :shares          50           :shares      200




     user=> portfolio
     [{:ticker "AAPL", :last-trade 203.25M, :open 204.50M, :shares 100}
      {:ticker "MSFT", :last-trade 29.12M, :open 29.08M, :shares 50}
      {:ticker "ORCL", :last-trade 21.90M, :open 21.83M, :shares 200}]
     user=> (sort-by :last-trade portfolio)
     ({:ticker "ORCL", :last-trade 21.90M, :open 21.83M, :shares 200}
      {:ticker "MSFT", :last-trade 29.12M, :open 29.08M, :shares 50}
      {:ticker "AAPL", :last-trade 203.25M, :open 204.50M, :shares 100})
     user=> (sort-by :shares portfolio)
     ({:ticker "MSFT", :last-trade 29.12M, :open 29.08M, :shares 50}
      {:ticker "AAPL", :last-trade 203.25M, :open 204.50M, :shares 100}
      {:ticker "ORCL", :last-trade 21.90M, :open 21.83M, :shares 200})
     user=>




                                              10                                © 2010 Howard Lewis Ship
Functional JavaScript




var portfolio = [ { ticker: "AAPL", lastTrade: 203.25, open: 204.50},
                  { ticker: "MSFT", lastTrade: 29.12, open: 29.08 },
                  { ticker: "ORCL", lastTrade: 21.90, open: 21.83 } ]

portfolio.sortBy(function (stock) { return stock.lastTrade }).toJSON()
[{"ticker": "ORCL", "lastTrade": 21.9, "open": 21.83},
 {"ticker": "MSFT", "lastTrade": 29.12, "open": 29.08},
 {"ticker": "AAPL", "lastTrade": 203.25, "open": 204.5}]




                                       11                                © 2010 Howard Lewis Ship
Clojure: The Language

            12          © 2010 Howard Lewis Ship
Reading Lisp

(defn render-json
  "Renders JSON content (typically, a map or a seq) as the
   response. The response content type is set to
   "application/json". Returns true."
  [env json-value]
  (let [response (-> env :servlet-api :response)]
    (.setContentType response "application/json")
    (with-open [writer (.getWriter Aargh!
                                    response)]
      (binding [*out* writer]
        (print-json json-value))))
  true)




                              13                      © 2010 Howard Lewis Ship
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))

                                  14                        © 2010 Howard Lewis Ship
Java: Complex Structure
int result = a * b - start + offset;



       Higher precendence, then left to right: ((a   * b) - start) + offset




                        +

                                                       (+
                   -            offset                   (-
                                                           (* a b)
         *              start                              start))
                                                         offset)
   a           b




                                            15                                © 2010 Howard Lewis Ship
Clojure:
 Form Is
Structure
    16   © 2010 Howard Lewis Ship
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

                           17                © 2010 Howard Lewis Ship
REPL and Compilation


                                                  Source Code

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

                            JVM

                    Operating System


                              18                      © 2010 Howard Lewis Ship
Clojure Literals


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




                           19       © 2010 Howard Lewis Ship
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




                           20                   © 2010 Howard Lewis Ship
Java Interop: Function Calls
    (.method-name receiver arguments…)



     (.setNamespaceAware factory true)



     (.. factory newSAXParser (parse src handler))



                     (.parse (.newSAXParser factory) src handler)




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




                              21                           © 2010 Howard Lewis Ship
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


                                22                 © 2010 Howard Lewis Ship
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

                          23                 © 2010 Howard Lewis Ship
Clojure Collections: Maps



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"
user=> (assoc m :company "TWD")
                                            its keys
{:company "TWD", :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!

                                  24                              © 2010 Howard Lewis Ship
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"}




                                   25                   © 2010 Howard Lewis Ship
Functional Programming

            26      © 2010 Howard Lewis Ship
My First Program



                            No it
         10   X = 1       doesn't!
         20   PRINT X
         30   X = X + 1
         40   GOTO 20




                 27              © 2010 Howard Lewis Ship
No
Mutable
 State
   28   © 2010 Howard Lewis Ship
No Side
Effects
   29     © 2010 Howard Lewis Ship
Purity
  30     © 2010 Howard Lewis Ship
Simplicity
Predictability
 Testability
      31    © 2010 Howard Lewis Ship
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
});
                                            32                                © 2010 Howard Lewis Ship
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(".");       Essence
  }
}, names);


                                         33                                 © 2010 Howard Lewis Ship
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=>




                                   34                       © 2010 Howard Lewis Ship
Composing Functions
(filter #(not (.startsWith % ".")) names)




                     function as
                     parameter to
                     function



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



                                                     Programming"
              function as
              return value

(filter (require-extension "gz") names)




                composing functions
                                          35                © 2010 Howard Lewis Ship
Java: Iterative Steps




                   36   © 2010 Howard Lewis Ship
Java: Data Encapsulated in
Objects
                Stock                Stock                Stock
             ticker: AAPL         ticker: MSFT        ticker: ORCL
          lastTrade: 203.25     lastTrade: 29.12    lastTrade: 21.90
            open: 204.50           open: 29.08         open: 21.83
              shares: 100           shares: 50          shares: 200



    public static List<Double> getOpens(List<Stock> portfolio)
    {
      List<Double> result = new ArrayList<Double>();

        for (Stock stock : portfolio)
        {
          result.add(stock.getOpen());
        }

        return result;
    }




                                     37                                © 2010 Howard Lewis Ship
Clojure: Flow of Transformations




                 38           © 2010 Howard Lewis Ship
Clojure: Data in Transformable
Collections
       :ticker     AAPL             :ticker          MSFT           :ticker     ORCL


     :last-trade   203.25         :last-trade        29.12        :last-trade   21.90

 {     :open       204.50   } {     :open            29.08   }{     :open       21.83       }
       :shares      100            :shares            50           :shares      200




user=> portfolio
[{:ticker "AAPL", :last-trade 203.25M, :open 204.50M, :shares 100}
 {:ticker "MSFT", :last-trade 29.12M, :open 29.08M, :shares 50}
 {:ticker "ORCL", :last-trade 21.90M, :open 21.83M, :shares 200}]
user=> (map :open portfolio)
(204.50M 29.08M 21.83M)
user=> (apply + (map #(* (:last-trade %) (:shares %)) portfolio))
26161.00M
user=> (map #(assoc % :delta (- (% :last-trade) (% :open))) portfolio)
({:delta -1.25M, :ticker "AAPL", :last-trade 203.25M, :open 204.50M, :shares 100}
 {:delta 0.04M, :ticker "MSFT", :last-trade 29.12M, :open 29.08M, :shares 50}
 {:delta 0.07M, :ticker "ORCL", :last-trade 21.90M, :open 21.83M, :shares 200})
user=>




                                                39                                  © 2010 Howard Lewis Ship
map




                                                               La
                                                                  z  y
                                f

                   :open acts as a function


      user=> (map :open portfolio)
      (204.5 29.08 21.83)
      user=> (defn last-trade-value
                [stock]
                (* (:last-trade stock) (:shares stock)))
      #'user/last-trade-value
      user=> (map last-trade-value portfolio)
      (20325.00M 1456.00M 4380.00M)
      user=>




                                    40                     © 2010 Howard Lewis Ship
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)


                                      41                           © 2010 Howard Lewis Ship
42   © 2010 Howard Lewis Ship
map




                                                                             La
                                                                                z  y
                                   f


                       N seqs # N parameters


user=> (map #(assoc %1 :sort-index %2)
            (reverse (sort-by :last-trade portfolio))
            (iterate inc 0))
({:sort-index 0, :ticker "AAPL", :last-trade 203.25M, :open 204.50M, :shares 100}
 {:sort-index 1, :ticker "MSFT", :last-trade 29.12M, :open 29.08M, :shares 50}
 {:sort-index 2, :ticker "ORCL", :last-trade 21.90M, :open 21.83M, :shares 200})
user=>




                                       43                                © 2010 Howard Lewis Ship
reduce

                                               f
user=> (map #(* (% :last-trade) (% :shares)) portfolio)
(20325.00M 1456.00M 4380.00M)
user=> (reduce + (map #(* (% :last-trade) (% :shares)) portfolio))
26161.00M
user=>


(reduce + (map #(* (% :last-trade) (% :shares)) portfolio))

(reduce + '(20325.00M 1456.00M 4380.00M))

(+ (+ 20325.00M 1456.00M) 4380.00M)

(+ 21781.00M 4380.00M)

26161.00M


                                         44                          © 2010 Howard Lewis Ship
reduce


                                                         f
                      user=> (def input-string "Clojure is a fascinating language with unique
                      capabilities and total integration with Java.")
                      #'user/input-string
                      user=> (seq input-string)
                      (C l o j u r e space i s space a space f a s c i n a
                      t i n g space l a n g u a g e space w i t h space u
                      n i q u e space c a p a b i l i t i e s space a n d
                      space t o t a l space i n t e g r a t i o n space w
                      i t h space J a v a .)
                      user=> (reduce
                               (fn [m k] (update-in m [k] #(inc (or % 0))))
Optional initial   value       {}
                               (seq input-string))
                      {space 12, a 12, b 1, C 1, c 2, d 1, e 5, f 1, g 4, h 2, i 11,
                       J 1, j 1, l 4, . 1, n 7, o 3, p 1, q 1, r 2, s 3, t 8, u 4,
                       v 1, w 2}
                      user=>


                                                   45                                © 2010 Howard Lewis Ship
filter / remove




                                                                      La
                                                                         z  y
                                              f
                                                  ?
user=> (remove #(< 100 (% :shares)) portfolio)
({:ticker "AAPL", :last-trade 203.25, :open 204.5, :shares 100}
 {:ticker "ORCL", :last-trade 21.9, :open 21.83, :shares 57})
user=> (filter #(< 100 (% :shares)) portfolio)
({:ticker "MSFT", :last-trade 29.12, :open 29.08, :shares 125})
user=>




                                         46                       © 2010 Howard Lewis Ship
for: list comprehension




                                                           La
                                                              z  y
user=> (for [suit [:hearts :clubs :spades :diamonds]
             value (range 1 4)]
         [suit value])
([:hearts 1] [:hearts 2] [:hearts 3]
 [:clubs 1] [:clubs 2] [:clubs 3]
 [:spades 1] [:spades 2] [:spades 3]
 [:diamonds 1] [:diamonds 2] [:diamonds 3])
user=> (for [x (range 0 4)
             y (range 0 (inc x))]
         [x y])
([0 0]
 [1 0] [1 1]
 [2 0] [2 1] [2 2]
 [3 0] [3 1] [3 2] [3 3])
user=> (for [x (range 0 9) :when (odd? x)
             y (range 1 (inc x))]
         [x y])
([1 1]
 [3 1] [3 2] [3 3]
 [5 1] [5 2] [5 3] [5 4] [5 5]
 [7 1] [7 2] [7 3] [7 4] [7 5] [7 6] [7 7])
user=>




                                         47            © 2010 Howard Lewis Ship
!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
                            © 2010 Howard Lewis Ship
Language Ownership

           49        © 2010 Howard Lewis Ship
Who Owns the Java Language?




    James Gosling        Mark Reinhold




                    50              © 2010 Howard Lewis Ship
Not You
   51     © 2010 Howard Lewis Ship
Control of the Compiler


                                                  Source Code

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

                            JVM

                    Operating System


                              52                      © 2010 Howard Lewis Ship
Who Owns Clojure?




            Rich Hickey




                53        © 2010 Howard Lewis Ship
Clojure: written in Clojure




                 54           © 2010 Howard Lewis Ship
Clojure Macros
                                       short circuit at
                                       first false/nil
                Reader

                                    (and a b c d)




               Evaluator         macro expansion
                                    and macro




               Bytecode      (let [and__4422__auto__ a]
                               (if and__4422__auto__
              Generation         (and b c d)
                                 and__4422__auto__))


          Recursively expanded



                      55                                  © 2010 Howard Lewis Ship
Macros # Special Forms
                   Code Forms




                     Macro
                   Expansion




        def   if    let        fn   .   …


                    Bytecode
                   Generation

                          56                © 2010 Howard Lewis Ship
Macros are Special Functions
(defmacro and
  "Evaluates exprs one at a time, from left to right. If a form
  returns logical false (nil or false), and returns that value and
  doesn't evaluate any of the other expressions, otherwise it returns
  the value of the last expr. (and) returns true."
  ([] true)
  ([x] x)
  ([x & next]
   `(let [and# ~x]
      (if and# (and ~@next) and#))))




• `(…) — Syntax Quote (allowing replacements)

• and# — Generate a new unique symbol

• ~x — Unquote x

• ~@next — Unquote next and splice in multiple values

                                         57                             © 2010 Howard Lewis Ship
Macros are Special Functions
(defmacro and
  ([] true)
  ([x] x)
                                            (and a b c d)
  ([x & next]
   `(let [and# ~x]
      (if and# (and ~@next) and#))))


•x#a
• next # '(b c d)
• Inside syntax quote:
   • and# # and__4422__auto__
   • ~x # a
   • ~next # '(b c d)
   • (and ~@next) # (and b c d)

                                       58                   © 2010 Howard Lewis Ship
Simplifying Boilerplate Code
public void testLink()
{
  IMocksControl control = EasyMock.createControl();
  HttpServletRequest request = control.newMock(HttpServletRequest.class);
  HttpServletResponse response = control.newMock(HttpServletResponse.class);

    EasyMock.expect(request.getContextPath()).andReturn("/ctx");
    EasyMock.expect(response.encodeURL("/ctx/accounts/list")).andReturn("*encoded*");

    control.replay();

    assertEquals(…, "*encoded*");

    control.verify();
}


           (deftest test-link
             (with-mocks [request HttpServletRequest
                          response HttpServletResponse]
               (:train
                 (expect .getContextPath request "/ctx")
                 (expect .encodeURL response "/ctx/accounts/list" "*encoded*"))
               (:test
                 (is (= (link request response list-accounts-with-loop)
                        "*encoded*")))))


                                            59                                 © 2010 Howard Lewis Ship
Embedded DSLs


 (defview root-index
   [env]
   :html [
     :head [
       :title [ "Cascade Blog" ]
     ]
     :body [
       :h1 [ "Cascade Blog" ]

                                    :html
        :ul { :class "recent-postings" } [
          (template-for [posting (recent-postings env)]
            :li [
               (render-link env show-posting (posting :id) (posting :title))
             ])               :head        :body
        ]
    ]
  ])
                       :title           :h1          :ul


              "Cascade Blog"       "Cascade Blog"          (template-for …)

                                        60                                    © 2010 Howard Lewis Ship
Macro Expansions
           (defn list-items [coll]
             (template
               (format "%d items" (count coll))
               :ul {:class :item-list} [
               (template-for [item coll] :li [item])))




               Expand simple          Extend Clojure
               placeholder to         language from
              executable code          within Clojure




   (defn list-items [coll]
     (cascade.internal.viewbuilder/combine
       (format "%d items" (count coll))
       (cascade.dom/element-node :ul {:class :item-list}
         (cascade.internal.viewbuilder/combine
           (for [item coll]
              (cascade.dom/element-node :li nil
                (cascade.internal.viewbuilder/combine item)))))))


                                 61                                 © 2010 Howard Lewis Ship
!More than anything else, I think it is the
ability of Lisp programs to manipulate
Lisp expressions that sets Lisp apart …
when I hear people complain about Lisp's
parentheses, it sounds to my ears like
someone saying: "I tried one of those
bananas, which you say are so delicious.
The white part was ok, but the yellow
part was very tough and tasted awful.""


Paul Graham
                                      © 2010 Howard Lewis Ship
Wrap Up

          63   © 2010 Howard Lewis Ship
Clojure
• 1.1 release: Dec 31 2009

• Simple, regular syntax

• Improves on Lisp: vectors, maps, sets
                                          http://www.clojure.org
• Fully integrates with Java

• Impressive functional & concurrency support

• Many features not covered here



                                64                      © 2010 Howard Lewis Ship
Stuart Halloway

                               Pragmatic Bookshelf




http://pragprog.com/titles/shcloj/programming-clojure

                          65                     © 2010 Howard Lewis Ship
http://java.ociweb.com/mark/clojure/article.html




                      66                  © 2010 Howard Lewis Ship
http://tapestryjava.blogspot.com




                        67         © 2010 Howard Lewis Ship
Object Oriented




                  68   © 2010 Howard Lewis Ship
Functional




             69   © 2010 Howard Lewis Ship
Image Credits
  © 2007 Jon Fife
  http://flickr.com/photos/good-karma/577632972/
                                                      © 2007 Casey Marshall
                               http://www.flickr.com/photos/rsdio/497112391/
  © 2009 Howard M. Lewis Ship
  http://www.flickr.com/photos/hlship/3603090614/
                                                       © 2009 Andrew Baird
                            http://www.flickr.com/photos/scruffy/3708615414/
  © 2008 Miles Sabin
  http://www.flickr.com/photos/montpelier/2915114545/
                                                            © 2003 A. Lipson
                           http://www.andrewlipson.com/escher/relativity.html
  © 2007 Alan Chia
  http://flickr.com/photos/seven13avenue/2080281038/
                                                © 2007 Woodley Wonderworks
                               http://flickr.com/photos/wwworks/2222523486/
  © Randall Munroe
  http://xkcd.com/297/
                                                       © 2008 Manu Gómez
                         http://www.flickr.com/photos/manugomi/2884678938/
  © 2008 Marcin Wichary
  http://www.flickr.com/photos/mwichary/2827326852/
                                                         © 2006 Marvin (PA)
                             http://www.flickr.com/photos/mscolly/145052885/

                                      70                                    © 2010 Howard Lewis Ship
Image Credits
  © 2007 John Kannenberg
  http://www.flickr.com/photos/jkannenberg/541057337/
                                                         © 2006 scott ogilvie
                             http://www.flickr.com/photos/scottog/100582274/
  © 2008 Ariel H.
  http://www.flickr.com/photos/fotosrotas/2730733412/




                                      71                                    © 2010 Howard Lewis Ship

Más contenido relacionado

La actualidad más candente

Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...Eelco Visser
 
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)lennartkats
 
JavaFX and Scala - Like Milk and Cookies
JavaFX and Scala - Like Milk and CookiesJavaFX and Scala - Like Milk and Cookies
JavaFX and Scala - Like Milk and CookiesStephen Chin
 
Cleaner APIs, Cleaner UIs with Visage (33rd Degrees)
Cleaner APIs, Cleaner UIs with Visage (33rd Degrees)Cleaner APIs, Cleaner UIs with Visage (33rd Degrees)
Cleaner APIs, Cleaner UIs with Visage (33rd Degrees)Stephen Chin
 
Node 관계형 데이터베이스_바인딩
Node 관계형 데이터베이스_바인딩Node 관계형 데이터베이스_바인딩
Node 관계형 데이터베이스_바인딩HyeonSeok Choi
 
Hacking JavaFX with Groovy, Clojure, Scala, and Visage: Stephen Chin
Hacking JavaFX with Groovy, Clojure, Scala, and Visage: Stephen ChinHacking JavaFX with Groovy, Clojure, Scala, and Visage: Stephen Chin
Hacking JavaFX with Groovy, Clojure, Scala, and Visage: Stephen Chinjaxconf
 
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
 
HBase Client APIs (for webapps?)
HBase Client APIs (for webapps?)HBase Client APIs (for webapps?)
HBase Client APIs (for webapps?)Nick Dimiduk
 
OSDC.fr 2012 :: Cascalog : progammation logique pour Hadoop
OSDC.fr 2012 :: Cascalog : progammation logique pour HadoopOSDC.fr 2012 :: Cascalog : progammation logique pour Hadoop
OSDC.fr 2012 :: Cascalog : progammation logique pour HadoopPublicis Sapient Engineering
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6Dmitry Soshnikov
 
concurrency with GPars
concurrency with GParsconcurrency with GPars
concurrency with GParsPaul King
 
Grails/Groovyによる開発事例紹介
Grails/Groovyによる開発事例紹介Grails/Groovyによる開発事例紹介
Grails/Groovyによる開発事例紹介Kiyotaka Oku
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with GroovyArturo Herrero
 

La actualidad más candente (20)

Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
 
tutorial5
tutorial5tutorial5
tutorial5
 
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
 
JavaFX and Scala - Like Milk and Cookies
JavaFX and Scala - Like Milk and CookiesJavaFX and Scala - Like Milk and Cookies
JavaFX and Scala - Like Milk and Cookies
 
ddd+scala
ddd+scaladdd+scala
ddd+scala
 
Cleaner APIs, Cleaner UIs with Visage (33rd Degrees)
Cleaner APIs, Cleaner UIs with Visage (33rd Degrees)Cleaner APIs, Cleaner UIs with Visage (33rd Degrees)
Cleaner APIs, Cleaner UIs with Visage (33rd Degrees)
 
Clojure And Swing
Clojure And SwingClojure And Swing
Clojure And Swing
 
ROracle
ROracle ROracle
ROracle
 
Spock and Geb in Action
Spock and Geb in ActionSpock and Geb in Action
Spock and Geb in Action
 
Node 관계형 데이터베이스_바인딩
Node 관계형 데이터베이스_바인딩Node 관계형 데이터베이스_바인딩
Node 관계형 데이터베이스_바인딩
 
Hacking JavaFX with Groovy, Clojure, Scala, and Visage: Stephen Chin
Hacking JavaFX with Groovy, Clojure, Scala, and Visage: Stephen ChinHacking JavaFX with Groovy, Clojure, Scala, and Visage: Stephen Chin
Hacking JavaFX with Groovy, Clojure, Scala, and Visage: Stephen Chin
 
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
 
JRuby hacking guide
JRuby hacking guideJRuby hacking guide
JRuby hacking guide
 
HBase Client APIs (for webapps?)
HBase Client APIs (for webapps?)HBase Client APIs (for webapps?)
HBase Client APIs (for webapps?)
 
OSDC.fr 2012 :: Cascalog : progammation logique pour Hadoop
OSDC.fr 2012 :: Cascalog : progammation logique pour HadoopOSDC.fr 2012 :: Cascalog : progammation logique pour Hadoop
OSDC.fr 2012 :: Cascalog : progammation logique pour Hadoop
 
FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6FalsyValues. Dmitry Soshnikov - ECMAScript 6
FalsyValues. Dmitry Soshnikov - ECMAScript 6
 
Hack reduce mr-intro
Hack reduce mr-introHack reduce mr-intro
Hack reduce mr-intro
 
concurrency with GPars
concurrency with GParsconcurrency with GPars
concurrency with GPars
 
Grails/Groovyによる開発事例紹介
Grails/Groovyによる開発事例紹介Grails/Groovyによる開発事例紹介
Grails/Groovyによる開発事例紹介
 
Functional Programming with Groovy
Functional Programming with GroovyFunctional Programming with Groovy
Functional Programming with Groovy
 

Destacado

Ring: Web Apps in Idiomatic Clojure
Ring: Web Apps in Idiomatic ClojureRing: Web Apps in Idiomatic Clojure
Ring: Web Apps in Idiomatic ClojureMark McGranaghan
 
Lisp Macros in 20 Minutes (Featuring Clojure)
Lisp Macros in 20 Minutes (Featuring Clojure)Lisp Macros in 20 Minutes (Featuring Clojure)
Lisp Macros in 20 Minutes (Featuring Clojure)Phil Calçado
 
Embracing Clojure: a journey into Clojure adoption
Embracing Clojure: a journey into Clojure adoptionEmbracing Clojure: a journey into Clojure adoption
Embracing Clojure: a journey into Clojure adoptionLuca Grulla
 
穆黎森:Interactive batch query at scale
穆黎森:Interactive batch query at scale穆黎森:Interactive batch query at scale
穆黎森:Interactive batch query at scalehdhappy001
 
Planificación y Control de Procesos (PCP)
Planificación y Control de Procesos (PCP)Planificación y Control de Procesos (PCP)
Planificación y Control de Procesos (PCP)Andre Marques Valio
 
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
 
Rabbit mq簡介(上)
Rabbit mq簡介(上)Rabbit mq簡介(上)
Rabbit mq簡介(上)共和 薛
 
Introduction to clojure
Introduction to clojureIntroduction to clojure
Introduction to clojureAbbas Raza
 
Using Clojure, NoSQL Databases and Functional-Style JavaScript to Write Gext-...
Using Clojure, NoSQL Databases and Functional-Style JavaScript to Write Gext-...Using Clojure, NoSQL Databases and Functional-Style JavaScript to Write Gext-...
Using Clojure, NoSQL Databases and Functional-Style JavaScript to Write Gext-...Stefan Richter
 
Clojure: The Art of Abstraction
Clojure: The Art of AbstractionClojure: The Art of Abstraction
Clojure: The Art of AbstractionAlex Miller
 
Machine Learning to Grow the World's Knowledge
Machine Learning to Grow  the World's KnowledgeMachine Learning to Grow  the World's Knowledge
Machine Learning to Grow the World's KnowledgeXavier Amatriain
 
DAMA Webinar - Big and Little Data Quality
DAMA Webinar - Big and Little Data QualityDAMA Webinar - Big and Little Data Quality
DAMA Webinar - Big and Little Data QualityDATAVERSITY
 
Visualising Data with Code
Visualising Data with CodeVisualising Data with Code
Visualising Data with CodeRi Liu
 
GPU Computing for Data Science
GPU Computing for Data Science GPU Computing for Data Science
GPU Computing for Data Science Domino Data Lab
 
Visual Design with Data
Visual Design with DataVisual Design with Data
Visual Design with DataSeth Familian
 

Destacado (16)

Ring: Web Apps in Idiomatic Clojure
Ring: Web Apps in Idiomatic ClojureRing: Web Apps in Idiomatic Clojure
Ring: Web Apps in Idiomatic Clojure
 
Lisp Macros in 20 Minutes (Featuring Clojure)
Lisp Macros in 20 Minutes (Featuring Clojure)Lisp Macros in 20 Minutes (Featuring Clojure)
Lisp Macros in 20 Minutes (Featuring Clojure)
 
Embracing Clojure: a journey into Clojure adoption
Embracing Clojure: a journey into Clojure adoptionEmbracing Clojure: a journey into Clojure adoption
Embracing Clojure: a journey into Clojure adoption
 
穆黎森:Interactive batch query at scale
穆黎森:Interactive batch query at scale穆黎森:Interactive batch query at scale
穆黎森:Interactive batch query at scale
 
Planificación y Control de Procesos (PCP)
Planificación y Control de Procesos (PCP)Planificación y Control de Procesos (PCP)
Planificación y Control de Procesos (PCP)
 
DSL in Clojure
DSL in ClojureDSL in Clojure
DSL in Clojure
 
From Java To Clojure (English version)
From Java To Clojure (English version)From Java To Clojure (English version)
From Java To Clojure (English version)
 
Rabbit mq簡介(上)
Rabbit mq簡介(上)Rabbit mq簡介(上)
Rabbit mq簡介(上)
 
Introduction to clojure
Introduction to clojureIntroduction to clojure
Introduction to clojure
 
Using Clojure, NoSQL Databases and Functional-Style JavaScript to Write Gext-...
Using Clojure, NoSQL Databases and Functional-Style JavaScript to Write Gext-...Using Clojure, NoSQL Databases and Functional-Style JavaScript to Write Gext-...
Using Clojure, NoSQL Databases and Functional-Style JavaScript to Write Gext-...
 
Clojure: The Art of Abstraction
Clojure: The Art of AbstractionClojure: The Art of Abstraction
Clojure: The Art of Abstraction
 
Machine Learning to Grow the World's Knowledge
Machine Learning to Grow  the World's KnowledgeMachine Learning to Grow  the World's Knowledge
Machine Learning to Grow the World's Knowledge
 
DAMA Webinar - Big and Little Data Quality
DAMA Webinar - Big and Little Data QualityDAMA Webinar - Big and Little Data Quality
DAMA Webinar - Big and Little Data Quality
 
Visualising Data with Code
Visualising Data with CodeVisualising Data with Code
Visualising Data with Code
 
GPU Computing for Data Science
GPU Computing for Data Science GPU Computing for Data Science
GPU Computing for Data Science
 
Visual Design with Data
Visual Design with DataVisual Design with Data
Visual Design with Data
 

Similar a Codemash-Clojure.pdf

Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)
Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)
Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)Howard Lewis Ship
 
Practical Clojure Programming
Practical Clojure ProgrammingPractical Clojure Programming
Practical Clojure ProgrammingHoward Lewis Ship
 
Clojure Intro
Clojure IntroClojure Intro
Clojure Introthnetos
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 
Getting started with Clojure
Getting started with ClojureGetting started with Clojure
Getting started with ClojureJohn Stevenson
 
ClojurianからみたElixir
ClojurianからみたElixirClojurianからみたElixir
ClojurianからみたElixirKent Ohashi
 
Scala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghScala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghStuart Roebuck
 
From Java to Parellel Clojure - Clojure South 2019
From Java to Parellel Clojure - Clojure South 2019From Java to Parellel Clojure - Clojure South 2019
From Java to Parellel Clojure - Clojure South 2019Leonardo Borges
 
T3chFest 2016 - The polyglot programmer
T3chFest 2016 - The polyglot programmerT3chFest 2016 - The polyglot programmer
T3chFest 2016 - The polyglot programmerDavid Muñoz Díaz
 
JavaOne報告会 Java SE/JavaFX 編 - JJUG CCC 2010 Fall
JavaOne報告会 Java SE/JavaFX 編 - JJUG CCC 2010 FallJavaOne報告会 Java SE/JavaFX 編 - JJUG CCC 2010 Fall
JavaOne報告会 Java SE/JavaFX 編 - JJUG CCC 2010 FallYuichi Sakuraba
 
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
 
Class 31: Deanonymizing
Class 31: DeanonymizingClass 31: Deanonymizing
Class 31: DeanonymizingDavid Evans
 

Similar a Codemash-Clojure.pdf (20)

Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)
Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)
Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)
 
Clojure Deep Dive
Clojure Deep DiveClojure Deep Dive
Clojure Deep Dive
 
EMFPath
EMFPathEMFPath
EMFPath
 
Practical Clojure Programming
Practical Clojure ProgrammingPractical Clojure Programming
Practical Clojure Programming
 
Clojure Intro
Clojure IntroClojure Intro
Clojure Intro
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
Current State of Coroutines
Current State of CoroutinesCurrent State of Coroutines
Current State of Coroutines
 
55j7
55j755j7
55j7
 
Hw09 Hadoop + Clojure
Hw09   Hadoop + ClojureHw09   Hadoop + Clojure
Hw09 Hadoop + Clojure
 
Getting started with Clojure
Getting started with ClojureGetting started with Clojure
Getting started with Clojure
 
ClojurianからみたElixir
ClojurianからみたElixirClojurianからみたElixir
ClojurianからみたElixir
 
Scala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghScala @ TechMeetup Edinburgh
Scala @ TechMeetup Edinburgh
 
From Java to Parellel Clojure - Clojure South 2019
From Java to Parellel Clojure - Clojure South 2019From Java to Parellel Clojure - Clojure South 2019
From Java to Parellel Clojure - Clojure South 2019
 
Hadoop + Clojure
Hadoop + ClojureHadoop + Clojure
Hadoop + Clojure
 
T3chFest 2016 - The polyglot programmer
T3chFest 2016 - The polyglot programmerT3chFest 2016 - The polyglot programmer
T3chFest 2016 - The polyglot programmer
 
JavaOne報告会 Java SE/JavaFX 編 - JJUG CCC 2010 Fall
JavaOne報告会 Java SE/JavaFX 編 - JJUG CCC 2010 FallJavaOne報告会 Java SE/JavaFX 編 - JJUG CCC 2010 Fall
JavaOne報告会 Java SE/JavaFX 編 - JJUG CCC 2010 Fall
 
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
 
Class 31: Deanonymizing
Class 31: DeanonymizingClass 31: Deanonymizing
Class 31: Deanonymizing
 
Reactive x
Reactive xReactive x
Reactive x
 

Más de 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
 
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
 
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
 

Más de Howard Lewis Ship (10)

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
 
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
 
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
 
Cascade
CascadeCascade
Cascade
 
Tapestry: State of the Union
Tapestry: State of the UnionTapestry: State of the Union
Tapestry: State of the Union
 

Codemash-Clojure.pdf

  • 1. Clojure: Functional Concurrency for the JVM Howard M. Lewis Ship TWD Consulting hlship@gmail.com 1 © 2010 Howard Lewis Ship
  • 2. Clojure: Why Functional Programming Matters Howard M. Lewis Ship TWD Consulting hlship@gmail.com 2 © 2010 Howard Lewis Ship
  • 3. Clojure: Towards the Essence of Programming Howard M. Lewis Ship TWD Consulting hlship@gmail.com 3 © 2010 Howard Lewis Ship
  • 4. essence noun the intrinsic nature or indispensable quality of something, esp. something abstract, that determines its character : conflict is the essence of drama. 4 © 2010 Howard Lewis Ship
  • 5. Mainstream Programming Applications Frameworks Libraries Language Operating System 5 © 2010 Howard Lewis Ship
  • 6. Ceremony vs. Essence 6 © 2010 Howard Lewis Ship
  • 7. Is your language ... 7 © 2010 Howard Lewis Ship
  • 8. … holding you back? 8 © 2010 Howard Lewis Ship
  • 9. Java: Data Encapsulated in Objects Stock Stock Stock ticker: AAPL ticker: MSFT ticker: ORCL lastTrade: 203.25 lastTrade: 29.12 lastTrade: 21.90 open: 204.50 open: 29.08 open: 21.83 shares: 100 shares: 50 shares: 200 public static void sortByLastTrade(List<Stock> portfolio) { Comparator<Stock> c = new Comparator<Stock>() { public int compare(Stock o1, Stock o2) { public static void sortByOpen(List<Stock> portfolio) return o1.getLastTrade() - o2.getLastTrade(); { } Comparator<Stock> c = new Comparator<Stock>() }; { public int compare(Stock o1, Stock o2) Collections.sort(portfolio, c); { } return o1.getOpen() - o2.getOpen(); } }; Collections.sort(portfolio, c); } 9 © 2010 Howard Lewis Ship
  • 10. Clojure: Data in Maps and Lists :ticker AAPL :ticker MSFT :ticker ORCL :last-trade 203.25 :last-trade 29.12 :last-trade 21.90 { :open 204.50 } { :open 29.08 }{ :open 21.83 } :shares 100 :shares 50 :shares 200 user=> portfolio [{:ticker "AAPL", :last-trade 203.25M, :open 204.50M, :shares 100} {:ticker "MSFT", :last-trade 29.12M, :open 29.08M, :shares 50} {:ticker "ORCL", :last-trade 21.90M, :open 21.83M, :shares 200}] user=> (sort-by :last-trade portfolio) ({:ticker "ORCL", :last-trade 21.90M, :open 21.83M, :shares 200} {:ticker "MSFT", :last-trade 29.12M, :open 29.08M, :shares 50} {:ticker "AAPL", :last-trade 203.25M, :open 204.50M, :shares 100}) user=> (sort-by :shares portfolio) ({:ticker "MSFT", :last-trade 29.12M, :open 29.08M, :shares 50} {:ticker "AAPL", :last-trade 203.25M, :open 204.50M, :shares 100} {:ticker "ORCL", :last-trade 21.90M, :open 21.83M, :shares 200}) user=> 10 © 2010 Howard Lewis Ship
  • 11. Functional JavaScript var portfolio = [ { ticker: "AAPL", lastTrade: 203.25, open: 204.50}, { ticker: "MSFT", lastTrade: 29.12, open: 29.08 }, { ticker: "ORCL", lastTrade: 21.90, open: 21.83 } ] portfolio.sortBy(function (stock) { return stock.lastTrade }).toJSON() [{"ticker": "ORCL", "lastTrade": 21.9, "open": 21.83}, {"ticker": "MSFT", "lastTrade": 29.12, "open": 29.08}, {"ticker": "AAPL", "lastTrade": 203.25, "open": 204.5}] 11 © 2010 Howard Lewis Ship
  • 12. Clojure: The Language 12 © 2010 Howard Lewis Ship
  • 13. Reading Lisp (defn render-json "Renders JSON content (typically, a map or a seq) as the response. The response content type is set to "application/json". Returns true." [env json-value] (let [response (-> env :servlet-api :response)] (.setContentType response "application/json") (with-open [writer (.getWriter Aargh! response)] (binding [*out* writer] (print-json json-value)))) true) 13 © 2010 Howard Lewis Ship
  • 14. 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)) 14 © 2010 Howard Lewis Ship
  • 15. Java: Complex Structure int result = a * b - start + offset; Higher precendence, then left to right: ((a * b) - start) + offset + (+ - offset (- (* a b) * start start)) offset) a b 15 © 2010 Howard Lewis Ship
  • 16. Clojure: Form Is Structure 16 © 2010 Howard Lewis Ship
  • 17. 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 17 © 2010 Howard Lewis Ship
  • 18. REPL and Compilation Source Code Repl Input Clojure User Classes Java Evaluator Compiler Clojure Source Files Java Libraries JVM Operating System 18 © 2010 Howard Lewis Ship
  • 19. Clojure Literals user=> 42 42 user=> "A Clojure String" "A Clojure String" user=> space space user=> A A user=> nil nil user=> :balance :balance user=> true true user=> false false 19 © 2010 Howard Lewis Ship
  • 20. 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 20 © 2010 Howard Lewis Ship
  • 21. Java Interop: Function Calls (.method-name receiver arguments…) (.setNamespaceAware factory true) (.. factory newSAXParser (parse src handler)) (.parse (.newSAXParser factory) src handler) factory.newSAXParser().parse(src, handler); 21 © 2010 Howard Lewis Ship
  • 22. 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 22 © 2010 Howard Lewis Ship
  • 23. 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 23 © 2010 Howard Lewis Ship
  • 24. Clojure Collections: Maps 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" user=> (assoc m :company "TWD") its keys {:company "TWD", :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! 24 © 2010 Howard Lewis Ship
  • 25. 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"} 25 © 2010 Howard Lewis Ship
  • 26. Functional Programming 26 © 2010 Howard Lewis Ship
  • 27. My First Program No it 10 X = 1 doesn't! 20 PRINT X 30 X = X + 1 40 GOTO 20 27 © 2010 Howard Lewis Ship
  • 28. No Mutable State 28 © 2010 Howard Lewis Ship
  • 29. No Side Effects 29 © 2010 Howard Lewis Ship
  • 30. Purity 30 © 2010 Howard Lewis Ship
  • 31. Simplicity Predictability Testability 31 © 2010 Howard Lewis Ship
  • 32. 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 }); 32 © 2010 Howard Lewis Ship
  • 33. 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("."); Essence } }, names); 33 © 2010 Howard Lewis Ship
  • 34. 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=> 34 © 2010 Howard Lewis Ship
  • 35. Composing Functions (filter #(not (.startsWith % ".")) names) function as parameter to function (defn require-extension [ext] !Closure Oriented (fn [file-name] (= ext (last (split-string file-name "."))))) Programming" function as return value (filter (require-extension "gz") names) composing functions 35 © 2010 Howard Lewis Ship
  • 36. Java: Iterative Steps 36 © 2010 Howard Lewis Ship
  • 37. Java: Data Encapsulated in Objects Stock Stock Stock ticker: AAPL ticker: MSFT ticker: ORCL lastTrade: 203.25 lastTrade: 29.12 lastTrade: 21.90 open: 204.50 open: 29.08 open: 21.83 shares: 100 shares: 50 shares: 200 public static List<Double> getOpens(List<Stock> portfolio) { List<Double> result = new ArrayList<Double>(); for (Stock stock : portfolio) { result.add(stock.getOpen()); } return result; } 37 © 2010 Howard Lewis Ship
  • 38. Clojure: Flow of Transformations 38 © 2010 Howard Lewis Ship
  • 39. Clojure: Data in Transformable Collections :ticker AAPL :ticker MSFT :ticker ORCL :last-trade 203.25 :last-trade 29.12 :last-trade 21.90 { :open 204.50 } { :open 29.08 }{ :open 21.83 } :shares 100 :shares 50 :shares 200 user=> portfolio [{:ticker "AAPL", :last-trade 203.25M, :open 204.50M, :shares 100} {:ticker "MSFT", :last-trade 29.12M, :open 29.08M, :shares 50} {:ticker "ORCL", :last-trade 21.90M, :open 21.83M, :shares 200}] user=> (map :open portfolio) (204.50M 29.08M 21.83M) user=> (apply + (map #(* (:last-trade %) (:shares %)) portfolio)) 26161.00M user=> (map #(assoc % :delta (- (% :last-trade) (% :open))) portfolio) ({:delta -1.25M, :ticker "AAPL", :last-trade 203.25M, :open 204.50M, :shares 100} {:delta 0.04M, :ticker "MSFT", :last-trade 29.12M, :open 29.08M, :shares 50} {:delta 0.07M, :ticker "ORCL", :last-trade 21.90M, :open 21.83M, :shares 200}) user=> 39 © 2010 Howard Lewis Ship
  • 40. map La z y f :open acts as a function user=> (map :open portfolio) (204.5 29.08 21.83) user=> (defn last-trade-value [stock] (* (:last-trade stock) (:shares stock))) #'user/last-trade-value user=> (map last-trade-value portfolio) (20325.00M 1456.00M 4380.00M) user=> 40 © 2010 Howard Lewis Ship
  • 41. 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) 41 © 2010 Howard Lewis Ship
  • 42. 42 © 2010 Howard Lewis Ship
  • 43. map La z y f N seqs # N parameters user=> (map #(assoc %1 :sort-index %2) (reverse (sort-by :last-trade portfolio)) (iterate inc 0)) ({:sort-index 0, :ticker "AAPL", :last-trade 203.25M, :open 204.50M, :shares 100} {:sort-index 1, :ticker "MSFT", :last-trade 29.12M, :open 29.08M, :shares 50} {:sort-index 2, :ticker "ORCL", :last-trade 21.90M, :open 21.83M, :shares 200}) user=> 43 © 2010 Howard Lewis Ship
  • 44. reduce f user=> (map #(* (% :last-trade) (% :shares)) portfolio) (20325.00M 1456.00M 4380.00M) user=> (reduce + (map #(* (% :last-trade) (% :shares)) portfolio)) 26161.00M user=> (reduce + (map #(* (% :last-trade) (% :shares)) portfolio)) (reduce + '(20325.00M 1456.00M 4380.00M)) (+ (+ 20325.00M 1456.00M) 4380.00M) (+ 21781.00M 4380.00M) 26161.00M 44 © 2010 Howard Lewis Ship
  • 45. reduce f user=> (def input-string "Clojure is a fascinating language with unique capabilities and total integration with Java.") #'user/input-string user=> (seq input-string) (C l o j u r e space i s space a space f a s c i n a t i n g space l a n g u a g e space w i t h space u n i q u e space c a p a b i l i t i e s space a n d space t o t a l space i n t e g r a t i o n space w i t h space J a v a .) user=> (reduce (fn [m k] (update-in m [k] #(inc (or % 0)))) Optional initial value {} (seq input-string)) {space 12, a 12, b 1, C 1, c 2, d 1, e 5, f 1, g 4, h 2, i 11, J 1, j 1, l 4, . 1, n 7, o 3, p 1, q 1, r 2, s 3, t 8, u 4, v 1, w 2} user=> 45 © 2010 Howard Lewis Ship
  • 46. filter / remove La z y f ? user=> (remove #(< 100 (% :shares)) portfolio) ({:ticker "AAPL", :last-trade 203.25, :open 204.5, :shares 100} {:ticker "ORCL", :last-trade 21.9, :open 21.83, :shares 57}) user=> (filter #(< 100 (% :shares)) portfolio) ({:ticker "MSFT", :last-trade 29.12, :open 29.08, :shares 125}) user=> 46 © 2010 Howard Lewis Ship
  • 47. for: list comprehension La z y user=> (for [suit [:hearts :clubs :spades :diamonds] value (range 1 4)] [suit value]) ([:hearts 1] [:hearts 2] [:hearts 3] [:clubs 1] [:clubs 2] [:clubs 3] [:spades 1] [:spades 2] [:spades 3] [:diamonds 1] [:diamonds 2] [:diamonds 3]) user=> (for [x (range 0 4) y (range 0 (inc x))] [x y]) ([0 0] [1 0] [1 1] [2 0] [2 1] [2 2] [3 0] [3 1] [3 2] [3 3]) user=> (for [x (range 0 9) :when (odd? x) y (range 1 (inc x))] [x y]) ([1 1] [3 1] [3 2] [3 3] [5 1] [5 2] [5 3] [5 4] [5 5] [7 1] [7 2] [7 3] [7 4] [7 5] [7 6] [7 7]) user=> 47 © 2010 Howard Lewis Ship
  • 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 © 2010 Howard Lewis Ship
  • 49. Language Ownership 49 © 2010 Howard Lewis Ship
  • 50. Who Owns the Java Language? James Gosling Mark Reinhold 50 © 2010 Howard Lewis Ship
  • 51. Not You 51 © 2010 Howard Lewis Ship
  • 52. Control of the Compiler Source Code Repl Input Clojure User Classes Java Evaluator Compiler Clojure Source Files Java Libraries JVM Operating System 52 © 2010 Howard Lewis Ship
  • 53. Who Owns Clojure? Rich Hickey 53 © 2010 Howard Lewis Ship
  • 54. Clojure: written in Clojure 54 © 2010 Howard Lewis Ship
  • 55. Clojure Macros short circuit at first false/nil Reader (and a b c d) Evaluator macro expansion and macro Bytecode (let [and__4422__auto__ a] (if and__4422__auto__ Generation (and b c d) and__4422__auto__)) Recursively expanded 55 © 2010 Howard Lewis Ship
  • 56. Macros # Special Forms Code Forms Macro Expansion def if let fn . … Bytecode Generation 56 © 2010 Howard Lewis Ship
  • 57. Macros are Special Functions (defmacro and "Evaluates exprs one at a time, from left to right. If a form returns logical false (nil or false), and returns that value and doesn't evaluate any of the other expressions, otherwise it returns the value of the last expr. (and) returns true." ([] true) ([x] x) ([x & next] `(let [and# ~x] (if and# (and ~@next) and#)))) • `(…) — Syntax Quote (allowing replacements) • and# — Generate a new unique symbol • ~x — Unquote x • ~@next — Unquote next and splice in multiple values 57 © 2010 Howard Lewis Ship
  • 58. Macros are Special Functions (defmacro and ([] true) ([x] x) (and a b c d) ([x & next] `(let [and# ~x] (if and# (and ~@next) and#)))) •x#a • next # '(b c d) • Inside syntax quote: • and# # and__4422__auto__ • ~x # a • ~next # '(b c d) • (and ~@next) # (and b c d) 58 © 2010 Howard Lewis Ship
  • 59. Simplifying Boilerplate Code public void testLink() { IMocksControl control = EasyMock.createControl(); HttpServletRequest request = control.newMock(HttpServletRequest.class); HttpServletResponse response = control.newMock(HttpServletResponse.class); EasyMock.expect(request.getContextPath()).andReturn("/ctx"); EasyMock.expect(response.encodeURL("/ctx/accounts/list")).andReturn("*encoded*"); control.replay(); assertEquals(…, "*encoded*"); control.verify(); } (deftest test-link (with-mocks [request HttpServletRequest response HttpServletResponse] (:train (expect .getContextPath request "/ctx") (expect .encodeURL response "/ctx/accounts/list" "*encoded*")) (:test (is (= (link request response list-accounts-with-loop) "*encoded*"))))) 59 © 2010 Howard Lewis Ship
  • 60. Embedded DSLs (defview root-index [env] :html [ :head [ :title [ "Cascade Blog" ] ] :body [ :h1 [ "Cascade Blog" ] :html :ul { :class "recent-postings" } [ (template-for [posting (recent-postings env)] :li [ (render-link env show-posting (posting :id) (posting :title)) ]) :head :body ] ] ]) :title :h1 :ul "Cascade Blog" "Cascade Blog" (template-for …) 60 © 2010 Howard Lewis Ship
  • 61. Macro Expansions (defn list-items [coll] (template (format "%d items" (count coll)) :ul {:class :item-list} [ (template-for [item coll] :li [item]))) Expand simple Extend Clojure placeholder to language from executable code within Clojure (defn list-items [coll] (cascade.internal.viewbuilder/combine (format "%d items" (count coll)) (cascade.dom/element-node :ul {:class :item-list} (cascade.internal.viewbuilder/combine (for [item coll] (cascade.dom/element-node :li nil (cascade.internal.viewbuilder/combine item))))))) 61 © 2010 Howard Lewis Ship
  • 62. !More than anything else, I think it is the ability of Lisp programs to manipulate Lisp expressions that sets Lisp apart … when I hear people complain about Lisp's parentheses, it sounds to my ears like someone saying: "I tried one of those bananas, which you say are so delicious. The white part was ok, but the yellow part was very tough and tasted awful."" Paul Graham © 2010 Howard Lewis Ship
  • 63. Wrap Up 63 © 2010 Howard Lewis Ship
  • 64. Clojure • 1.1 release: Dec 31 2009 • Simple, regular syntax • Improves on Lisp: vectors, maps, sets http://www.clojure.org • Fully integrates with Java • Impressive functional & concurrency support • Many features not covered here 64 © 2010 Howard Lewis Ship
  • 65. Stuart Halloway Pragmatic Bookshelf http://pragprog.com/titles/shcloj/programming-clojure 65 © 2010 Howard Lewis Ship
  • 66. http://java.ociweb.com/mark/clojure/article.html 66 © 2010 Howard Lewis Ship
  • 67. http://tapestryjava.blogspot.com 67 © 2010 Howard Lewis Ship
  • 68. Object Oriented 68 © 2010 Howard Lewis Ship
  • 69. Functional 69 © 2010 Howard Lewis Ship
  • 70. Image Credits © 2007 Jon Fife http://flickr.com/photos/good-karma/577632972/ © 2007 Casey Marshall http://www.flickr.com/photos/rsdio/497112391/ © 2009 Howard M. Lewis Ship http://www.flickr.com/photos/hlship/3603090614/ © 2009 Andrew Baird http://www.flickr.com/photos/scruffy/3708615414/ © 2008 Miles Sabin http://www.flickr.com/photos/montpelier/2915114545/ © 2003 A. Lipson http://www.andrewlipson.com/escher/relativity.html © 2007 Alan Chia http://flickr.com/photos/seven13avenue/2080281038/ © 2007 Woodley Wonderworks http://flickr.com/photos/wwworks/2222523486/ © Randall Munroe http://xkcd.com/297/ © 2008 Manu Gómez http://www.flickr.com/photos/manugomi/2884678938/ © 2008 Marcin Wichary http://www.flickr.com/photos/mwichary/2827326852/ © 2006 Marvin (PA) http://www.flickr.com/photos/mscolly/145052885/ 70 © 2010 Howard Lewis Ship
  • 71. Image Credits © 2007 John Kannenberg http://www.flickr.com/photos/jkannenberg/541057337/ © 2006 scott ogilvie http://www.flickr.com/photos/scottog/100582274/ © 2008 Ariel H. http://www.flickr.com/photos/fotosrotas/2730733412/ 71 © 2010 Howard Lewis Ship