SlideShare a Scribd company logo
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
Structural View
  defn render-json env json-value
    let
      response -> env :servlet-api :response

     .setContentType response "application/json"
     with-open
       writer .getWriter response

         binding
           *out* writer

           print-json json-value




                          14                       © 2010 Howard Lewis Ship
Java: Complex Structure
int f = 9 * c / 5 + 32;



      Higher precendence, then left to right: ((9   * c) / 5) + 32




                       +

                                                      (+
                  /          32                         (/
                                                          (* 9 c)
        *             5                                   5)
                                                        32)
  9           c




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

                                  17                        © 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

                           18                © 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


                              19                      © 2010 Howard Lewis Ship
Clojure Literals


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




                            20         © 2010 Howard Lewis Ship
Numeric Literals


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


                                       BigDecimal




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


    factory.setNamespaceAware(true)




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


    ( .. factory newSaxParser (
    (..                       (parse src handler))
                                                ))




                               22                    © 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


                                23                 © 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]




                          24                 © 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"
user=> (assoc m :company "TWD")
{:company "TWD", :last-name "Lewis Ship", :first-name "Howard"}
user=> m
{:last-name "Lewis Ship", :first-name "Howard"}
user=> (get m:ssn)
nil




                                  25                              © 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
user=> (conj s "Howard")
#{"Howard" "Jim" "Molly" "Suzanne"}
user=> (conj s "Scott")
#{"Howard" "Jim" "Molly" "Suzanne" "Scott"}




                                  26                 © 2010 Howard Lewis Ship
Functional Programming

            27      © 2010 Howard Lewis Ship
My First Program



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




                 28              © 2010 Howard Lewis Ship
No
Mutable
 State
   29   © 2010 Howard Lewis Ship
No Side
Effects
   30     © 2010 Howard Lewis Ship
Purity
  31     © 2010 Howard Lewis Ship
Simplicity
Predictability
 Testability
      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 #(get % :open) portfolio)
(204.50M 29.08M 21.83M)
user=>




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




                                                40                                  © 2010 Howard Lewis Ship
map




                                                               La
                                                                   zy
                               f

           keywords acts as functions

           (:keyword map) == (get map :keyword)

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




                                   41                      © 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)


                                      42                           © 2010 Howard Lewis Ship
43   © 2010 Howard Lewis Ship
map




                                                                             La
                                                                                 zy
                                   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=>




                                       44                                © 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


                                         45                          © 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=>


                                                   46                                © 2010 Howard Lewis Ship
filter / remove




                                                                      La
                                                                          zy
                                              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=>




                                         47                       © 2010 Howard Lewis Ship
for: list comprehension




                                                           La
                                                               zy
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=>




                                         48            © 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

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




    James Gosling        Mark Reinhold




                    51              © 2010 Howard Lewis Ship
Not You
   52     © 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


                              53                      © 2010 Howard Lewis Ship
Who Owns Clojure?




            Rich Hickey




                54        © 2010 Howard Lewis Ship
Clojure: written in Clojure




                 55           © 2010 Howard Lewis Ship
Short Circuits
                 && stops with first false


if (person.isPharaoh() &&                                   (if
    person.isDead() &&                                        (all-true
    constructPyramid())                                         (.isPharaoh person)
{                                                               (.isDead person)
  person.bury();                                                (construct-pyramid))
}                                                             (.bury person))



                            all parameters to function all-true evaluated first



                 public static boolean allTrue(boolean... inputs)
                 {
                   for (boolean input : inputs)
                   {
                     if (!input) return false;
                   }

                     return true;
                 }

                                            56                                   © 2010 Howard Lewis Ship
Caution:
Head Exploding Zone
            57        © 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



                      58                                  © 2010 Howard Lewis Ship
Macros ➠ Special Forms
                   Code Forms




                     Macro
                   Expansion




        def   if    let        fn   .   …


                    Bytecode
                   Generation

                          59                © 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

                                         60                             © 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)

                                       61                   © 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*")))))


                                            62                                 © 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 …)

                                        63                                    © 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)))))))


                                 64                                 © 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

          66   © 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.




                          67                     © 2010 Howard Lewis Ship
Control is the
  Essence of
Programming
      68    © 2010 Howard Lewis Ship
Evaluation
    69   © 2010 Howard Lewis Ship
If
When
How
 70    © 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



                                71                      © 2010 Howard Lewis Ship
Stuart Halloway

                               Pragmatic Bookshelf




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

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




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




                        74         © 2010 Howard Lewis Ship
Object Oriented




                  75   © 2010 Howard Lewis Ship
Functional




             76   © 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/

                                      77                                    © 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/
                                                  © 2006 John Ryan Brubaker
                       http://www.flickr.com/photos/subconscience/297682093/




                                      78                                    © 2010 Howard Lewis Ship

More Related Content

PDF
Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)
PDF
Codemash-Clojure.pdf
PPTX
JavaFX 2.0 With Alternative Languages - JavaOne 2011
PDF
Clojure: Functional Concurrency for the JVM (presented at OSCON)
ZIP
Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)
PPTX
Hacking JavaFX with Groovy, Clojure, Scala, and Visage
PPTX
JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...
PDF
Backbone.js: Run your Application Inside The Browser
Clojure: Towards The Essence Of Programming (What's Next? Conference, May 2011)
Codemash-Clojure.pdf
JavaFX 2.0 With Alternative Languages - JavaOne 2011
Clojure: Functional Concurrency for the JVM (presented at OSCON)
Clojure: Functional Concurrency for the JVM (presented at Open Source Bridge)
Hacking JavaFX with Groovy, Clojure, Scala, and Visage
JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...
Backbone.js: Run your Application Inside The Browser

What's hot (20)

PPTX
JavaFX and Scala - Like Milk and Cookies
PPT
Cleaner APIs, Cleaner UIs with Visage (33rd Degrees)
KEY
ddd+scala
PDF
Hacking JavaFX with Groovy, Clojure, Scala, and Visage: Stephen Chin
PDF
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
PDF
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
PPTX
ScalaDays 2014 - Reactive Scala 3D Game Engine
PDF
Scala in practice
PDF
G*ワークショップ in 仙台 Grails(とことん)入門
PDF
OSDC.fr 2012 :: Cascalog : progammation logique pour Hadoop
PDF
Hack reduce mr-intro
PDF
Cutting Edge Data Processing with PHP & XQuery
PDF
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
PDF
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion
PDF
JDK Power Tools
PPTX
Database security
PDF
Doc Parsers Api Cheatsheet 1 0
PDF
Spock and Geb
PDF
FalsyValues. Dmitry Soshnikov - ECMAScript 6
PPTX
Moving from JFreeChart to JavaFX with JavaFX Chart Extensions
JavaFX and Scala - Like Milk and Cookies
Cleaner APIs, Cleaner UIs with Visage (33rd Degrees)
ddd+scala
Hacking JavaFX with Groovy, Clojure, Scala, and Visage: Stephen Chin
Model-Driven Software Development - Pretty-Printing, Editor Services, Term Re...
Domain-Specific Languages for Composable Editor Plugins (LDTA 2009)
ScalaDays 2014 - Reactive Scala 3D Game Engine
Scala in practice
G*ワークショップ in 仙台 Grails(とことん)入門
OSDC.fr 2012 :: Cascalog : progammation logique pour Hadoop
Hack reduce mr-intro
Cutting Edge Data Processing with PHP & XQuery
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion
JDK Power Tools
Database security
Doc Parsers Api Cheatsheet 1 0
Spock and Geb
FalsyValues. Dmitry Soshnikov - ECMAScript 6
Moving from JFreeChart to JavaFX with JavaFX Chart Extensions
Ad

Similar to Clojure: Towards The Essence of Programming (20)

PPTX
Switching from java to groovy
PDF
A Tour Through the Groovy Ecosystem
PDF
OpenLogic
PDF
Clojure Deep Dive
PDF
Introduction to clojure
PDF
Groovy On Trading Desk (2010)
PDF
Clojure basics
PDF
Clojure - A new Lisp
PPTX
All about scala
PPT
Groovy presentation
PDF
Using Java from Ruby with JRuby IRB
PDF
Clojure - A practical LISP for the JVM
KEY
Scala Introduction
PDF
Introductionto fp with groovy
PDF
Introduction to Python
PDF
03 Geographic scripting in uDig - halfway between user and developer
PDF
Pune Clojure Course Outline
PPTX
Scala, Play 2.0 & Cloud Foundry
PPTX
Java fundamentals
PDF
Scala, Akka, and Play: An Introduction on Heroku
Switching from java to groovy
A Tour Through the Groovy Ecosystem
OpenLogic
Clojure Deep Dive
Introduction to clojure
Groovy On Trading Desk (2010)
Clojure basics
Clojure - A new Lisp
All about scala
Groovy presentation
Using Java from Ruby with JRuby IRB
Clojure - A practical LISP for the JVM
Scala Introduction
Introductionto fp with groovy
Introduction to Python
03 Geographic scripting in uDig - halfway between user and developer
Pune Clojure Course Outline
Scala, Play 2.0 & Cloud Foundry
Java fundamentals
Scala, Akka, and Play: An Introduction on Heroku
Ad

More from Howard Lewis Ship (11)

PDF
Testing Web Applications with GEB
PDF
Spock: A Highly Logical Way To Test
PDF
Modern Application Foundations: Underscore and Twitter Bootstrap
KEY
Have Your Cake and Eat It Too: Meta-Programming Techniques for Java
PDF
Arduino: Open Source Hardware Hacking from the Software Nerd Perspective
PDF
Practical Clojure Programming
PDF
Codemash-Tapestry.pdf
PDF
Tapestry 5: Java Power, Scripting Ease
PDF
Brew up a Rich Web Application with Cappuccino
PDF
PDF
Tapestry: State of the Union
Testing Web Applications with GEB
Spock: A Highly Logical Way To Test
Modern Application Foundations: Underscore and Twitter Bootstrap
Have Your Cake and Eat It Too: Meta-Programming Techniques for Java
Arduino: Open Source Hardware Hacking from the Software Nerd Perspective
Practical Clojure Programming
Codemash-Tapestry.pdf
Tapestry 5: Java Power, Scripting Ease
Brew up a Rich Web Application with Cappuccino
Tapestry: State of the Union

Recently uploaded (20)

PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
cuic standard and advanced reporting.pdf
PPTX
Machine Learning_overview_presentation.pptx
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Review of recent advances in non-invasive hemoglobin estimation
PPTX
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
PDF
Assigned Numbers - 2025 - Bluetooth® Document
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
Empathic Computing: Creating Shared Understanding
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
DOCX
The AUB Centre for AI in Media Proposal.docx
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
Machine learning based COVID-19 study performance prediction
PDF
Electronic commerce courselecture one. Pdf
PDF
A comparative analysis of optical character recognition models for extracting...
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
20250228 LYD VKU AI Blended-Learning.pptx
cuic standard and advanced reporting.pdf
Machine Learning_overview_presentation.pptx
Network Security Unit 5.pdf for BCA BBA.
Review of recent advances in non-invasive hemoglobin estimation
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
Assigned Numbers - 2025 - Bluetooth® Document
The Rise and Fall of 3GPP – Time for a Sabbatical?
Empathic Computing: Creating Shared Understanding
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
MYSQL Presentation for SQL database connectivity
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
The AUB Centre for AI in Media Proposal.docx
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Machine learning based COVID-19 study performance prediction
Electronic commerce courselecture one. Pdf
A comparative analysis of optical character recognition models for extracting...

Clojure: Towards The Essence of Programming

  • 1. Clojure: Functional Concurrency for the JVM Howard M. Lewis Ship TWD Consulting [email protected] 1 © 2010 Howard Lewis Ship
  • 2. Clojure: Why Functional Programming Matters Howard M. Lewis Ship TWD Consulting [email protected] 2 © 2010 Howard Lewis Ship
  • 3. Clojure: Towards the Essence of Programming Howard M. Lewis Ship TWD Consulting [email protected] 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. Structural View defn render-json env json-value let response -> env :servlet-api :response .setContentType response "application/json" with-open writer .getWriter response binding *out* writer print-json json-value 14 © 2010 Howard Lewis Ship
  • 15. Java: Complex Structure int f = 9 * c / 5 + 32; Higher precendence, then left to right: ((9 * c) / 5) + 32 + (+ / 32 (/ (* 9 c) * 5 5) 32) 9 c 15 © 2010 Howard Lewis Ship
  • 16. Clojure: Form Is Structure 16 © 2010 Howard Lewis Ship
  • 17. 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)) 17 © 2010 Howard Lewis Ship
  • 18. 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 18 © 2010 Howard Lewis Ship
  • 19. REPL and Compilation Source Code Repl Input Clojure User Classes Java Evaluator Compiler Clojure Source Files Java Libraries JVM Operating System 19 © 2010 Howard Lewis Ship
  • 20. Clojure Literals user=> "A Clojure String" "A Clojure String" user=> space space user=> A A user=> nil Java null nil user=> :balance :balance user=> true true user=> false false 20 © 2010 Howard Lewis Ship
  • 21. Numeric Literals user=> 5 5 user=> 5.001 5.001 Ratio user=> 22/7 22/7 user=> (* 2 22/7) 44/7 user=> (* 100000 100000 100000) BigInteger 1000000000000000 user=> (+ 5. 0.000000000000000001) 5.0 user=> (+ 5.0M 0.000000000000000001M) 5.000000000000000001M BigDecimal 21 © 2010 Howard Lewis Ship
  • 22. Java Interop: Function Calls (.method-name receiver arguments…) factory.setNamespaceAware(true) factory.newSaxParser().parse(src, handler) ( .. factory newSaxParser ( (.. (parse src handler)) )) 22 © 2010 Howard Lewis Ship
  • 23. 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 23 © 2010 Howard Lewis Ship
  • 24. 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] 24 © 2010 Howard Lewis Ship
  • 25. 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" user=> (assoc m :company "TWD") {:company "TWD", :last-name "Lewis Ship", :first-name "Howard"} user=> m {:last-name "Lewis Ship", :first-name "Howard"} user=> (get m:ssn) nil 25 © 2010 Howard Lewis Ship
  • 26. 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 user=> (conj s "Howard") #{"Howard" "Jim" "Molly" "Suzanne"} user=> (conj s "Scott") #{"Howard" "Jim" "Molly" "Suzanne" "Scott"} 26 © 2010 Howard Lewis Ship
  • 27. Functional Programming 27 © 2010 Howard Lewis Ship
  • 28. My First Program No it 10 X = 1 doesn't! 20 PRINT X 30 X = X + 1 40 GOTO 20 28 © 2010 Howard Lewis Ship
  • 29. No Mutable State 29 © 2010 Howard Lewis Ship
  • 30. No Side Effects 30 © 2010 Howard Lewis Ship
  • 31. Purity 31 © 2010 Howard Lewis Ship
  • 32. Simplicity Predictability Testability 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 #(get % :open) portfolio) (204.50M 29.08M 21.83M) user=> 39 © 2010 Howard Lewis Ship
  • 40. 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=> (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=> 40 © 2010 Howard Lewis Ship
  • 41. map La zy f keywords acts as functions (:keyword map) == (get map :keyword) 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=> 41 © 2010 Howard Lewis Ship
  • 42. 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) 42 © 2010 Howard Lewis Ship
  • 43. 43 © 2010 Howard Lewis Ship
  • 44. map La zy 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=> 44 © 2010 Howard Lewis Ship
  • 45. 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 45 © 2010 Howard Lewis Ship
  • 46. 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=> 46 © 2010 Howard Lewis Ship
  • 47. filter / remove La zy 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=> 47 © 2010 Howard Lewis Ship
  • 48. for: list comprehension La zy 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=> 48 © 2010 Howard Lewis Ship
  • 49. ❝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
  • 50. Language Ownership 50 © 2010 Howard Lewis Ship
  • 51. Who Owns the Java Language? James Gosling Mark Reinhold 51 © 2010 Howard Lewis Ship
  • 52. Not You 52 © 2010 Howard Lewis Ship
  • 53. Control of the Compiler Source Code Repl Input Clojure User Classes Java Evaluator Compiler Clojure Source Files Java Libraries JVM Operating System 53 © 2010 Howard Lewis Ship
  • 54. Who Owns Clojure? Rich Hickey 54 © 2010 Howard Lewis Ship
  • 55. Clojure: written in Clojure 55 © 2010 Howard Lewis Ship
  • 56. Short Circuits && stops with first false if (person.isPharaoh() && (if person.isDead() && (all-true constructPyramid()) (.isPharaoh person) { (.isDead person) person.bury(); (construct-pyramid)) } (.bury person)) all parameters to function all-true evaluated first public static boolean allTrue(boolean... inputs) { for (boolean input : inputs) { if (!input) return false; } return true; } 56 © 2010 Howard Lewis Ship
  • 57. Caution: Head Exploding Zone 57 © 2010 Howard Lewis Ship
  • 58. 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 58 © 2010 Howard Lewis Ship
  • 59. Macros ➠ Special Forms Code Forms Macro Expansion def if let fn . … Bytecode Generation 59 © 2010 Howard Lewis Ship
  • 60. 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 60 © 2010 Howard Lewis Ship
  • 61. 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) 61 © 2010 Howard Lewis Ship
  • 62. 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*"))))) 62 © 2010 Howard Lewis Ship
  • 63. 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 …) 63 © 2010 Howard Lewis Ship
  • 64. 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))))))) 64 © 2010 Howard Lewis Ship
  • 65. ❝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
  • 66. Wrap Up 66 © 2010 Howard Lewis Ship
  • 67. essence noun the intrinsic nature or indispensable quality of something, esp. something abstract, that determines its character : conflict is the essence of drama. 67 © 2010 Howard Lewis Ship
  • 68. Control is the Essence of Programming 68 © 2010 Howard Lewis Ship
  • 69. Evaluation 69 © 2010 Howard Lewis Ship
  • 70. If When How 70 © 2010 Howard Lewis Ship
  • 71. 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 71 © 2010 Howard Lewis Ship
  • 72. Stuart Halloway Pragmatic Bookshelf http://pragprog.com/titles/shcloj/programming-clojure 72 © 2010 Howard Lewis Ship
  • 75. Object Oriented 75 © 2010 Howard Lewis Ship
  • 76. Functional 76 © 2010 Howard Lewis Ship
  • 77. 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/ 77 © 2010 Howard Lewis Ship
  • 78. 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/ © 2006 John Ryan Brubaker http://www.flickr.com/photos/subconscience/297682093/ 78 © 2010 Howard Lewis Ship