Clojure:
Functional
Concurrency for
the JVM
Howard M. Lewis Ship
TWD Consulting
hlship@gmail.com
                1      © ...
Clojure: Why
Functional
Programming
Matters
Howard M. Lewis Ship
TWD Consulting
hlship@gmail.com
                2      © ...
Clojure: Towards
the Essence of
Programming
Howard M. Lewis Ship
TWD Consulting
hlship@gmail.com
                3      © ...
essence
noun
the intrinsic nature or indispensable quality of
something, esp. something abstract, that
determines its char...
Mainstream Programming

         Applications

         Frameworks

           Libraries

          Language

       Opera...
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  ...
Clojure: Data in Maps and Lists
       :ticker     AAPL             :ticker        MSFT           :ticker     ORCL


     ...
Functional JavaScript




var portfolio = [ { ticker: "AAPL", lastTrade: 203.25, open: 204.50},
                  { ticker...
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 conte...
Code is Data

                 Quoted list of
'(1 2 3)         numbers




(biggest 5 42)                Function call

  ...
Java: Complex Structure
int result = a * b - start + offset;



       Higher precendence, then left to right: ((a   * b) ...
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 ...
REPL and Compilation


                                                  Source Code

Repl Input                 Clojure
 ...
Clojure Literals


        user=> 42
        42
        user=> "A Clojure String"
        "A Clojure String"
        user=...
Clojure Literals


        user=> 5
        5
        user=> 5.001
        5.001
        user=> 22/7
        22/7
        ...
Java Interop: Function Calls
    (.method-name receiver arguments…)



     (.setNamespaceAware factory true)



     (.. ...
Clojure Collections: Lists




                            4
                                     lst
user=> (def lst '(1 ...
Clojure Collections: Vectors

       user=> (def v [:moe :larry :curly])
       #=(var user/v)
       user=> v
       [:mo...
Clojure Collections: Maps



user=> (def m {:first-name "Howard" :last-name "Lewis Ship"})
#=(var user/m)
user=> m
{:last-...
Clojure Collections: Sets


user=> (def s #{"Howard" "Suzanne" "Molly" "Jim"})
#=(var user/s)
user=> s
#{"Howard" "Jim" "M...
Functional Programming

            26      © 2010 Howard Lewis Ship
My First Program



                            No it
         10   X = 1       doesn't!
         20   PRINT X
         30...
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 Hi...
Functional Java Collections

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

public static <T> Collection<T>...
Functional Clojure Collections
                          Function
          Anonymous       parameter
          function

...
Composing Functions
(filter #(not (.startsWith % ".")) names)




                     function as
                     pa...
Java: Iterative Steps




                   36   © 2010 Howard Lewis Ship
Java: Data Encapsulated in
Objects
                Stock                Stock                Stock
             ticker: AA...
Clojure: Flow of Transformations




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




                                                               La
                                                ...
Laziness is
                                             a Virtue




user=>   (take   20 (iterate inc 1))
(1 2 3   4 5 6 ...
42   © 2010 Howard Lewis Ship
map




                                                                             La
                                  ...
reduce

                                               f
user=> (map #(* (% :last-trade) (% :shares)) portfolio)
(20325.00...
reduce


                                                         f
                      user=> (def input-string "Clojur...
filter / remove




                                                                      La
                              ...
for: list comprehension




                                                           La
                                ...
!Somehow the idea of reusability
got attached to object-oriented
programming in the 1980s, and
no amount of evidence to th...
Language Ownership

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




    James Gosling        Mark Reinhold




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


                                                  Source Code

Repl Input                 Clojur...
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/n...
Macros # Special Forms
                   Code Forms




                     Macro
                   Expansion




     ...
Macros are Special Functions
(defmacro and
  "Evaluates exprs one at a time, from left to right. If a form
  returns logic...
Macros are Special Functions
(defmacro and
  ([] true)
  ([x] x)
                                            (and a b c d)...
Simplifying Boilerplate Code
public void testLink()
{
  IMocksControl control = EasyMock.createControl();
  HttpServletReq...
Embedded DSLs


 (defview root-index
   [env]
   :html [
     :head [
       :title [ "Cascade Blog" ]
     ]
     :body [...
Macro Expansions
           (defn list-items [coll]
             (template
               (format "%d items" (count coll))...
!More than anything else, I think it is the
ability of Lisp programs to manipulate
Lisp expressions that sets Lisp apart …...
Wrap Up

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

• Simple, regular syntax

• Improves on Lisp: vectors, maps, sets
                    ...
Stuart Halloway

                               Pragmatic Bookshelf




http://pragprog.com/titles/shcloj/programming-cloj...
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/
                                          ...
Image Credits
  © 2007 John Kannenberg
  http://www.flickr.com/photos/jkannenberg/541057337/
                              ...
Upcoming SlideShare
Loading in...5
×

Codemash-Clojure.pdf

3,026

Published on

0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,026
On Slideshare
0
From Embeds
0
Number of Embeds
15
Actions
Shares
0
Downloads
69
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Codemash-Clojure.pdf

  1. 1. Clojure: Functional Concurrency for the JVM Howard M. Lewis Ship TWD Consulting hlship@gmail.com 1 © 2010 Howard Lewis Ship
  2. 2. Clojure: Why Functional Programming Matters Howard M. Lewis Ship TWD Consulting hlship@gmail.com 2 © 2010 Howard Lewis Ship
  3. 3. Clojure: Towards the Essence of Programming Howard M. Lewis Ship TWD Consulting hlship@gmail.com 3 © 2010 Howard Lewis Ship
  4. 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. 5. Mainstream Programming Applications Frameworks Libraries Language Operating System 5 © 2010 Howard Lewis Ship
  6. 6. Ceremony vs. Essence 6 © 2010 Howard Lewis Ship
  7. 7. Is your language ... 7 © 2010 Howard Lewis Ship
  8. 8. … holding you back? 8 © 2010 Howard Lewis Ship
  9. 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. 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. 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. 12. Clojure: The Language 12 © 2010 Howard Lewis Ship
  13. 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. 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. 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. 16. Clojure: Form Is Structure 16 © 2010 Howard Lewis Ship
  17. 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. 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. 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. 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. 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. 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. 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. 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. 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. 26. Functional Programming 26 © 2010 Howard Lewis Ship
  27. 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. 28. No Mutable State 28 © 2010 Howard Lewis Ship
  29. 29. No Side Effects 29 © 2010 Howard Lewis Ship
  30. 30. Purity 30 © 2010 Howard Lewis Ship
  31. 31. Simplicity Predictability Testability 31 © 2010 Howard Lewis Ship
  32. 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. 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. 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. 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. 36. Java: Iterative Steps 36 © 2010 Howard Lewis Ship
  37. 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. 38. Clojure: Flow of Transformations 38 © 2010 Howard Lewis Ship
  39. 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. 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. 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. 42 © 2010 Howard Lewis Ship
  43. 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. 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. 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. 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. 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. 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. 49. Language Ownership 49 © 2010 Howard Lewis Ship
  50. 50. Who Owns the Java Language? James Gosling Mark Reinhold 50 © 2010 Howard Lewis Ship
  51. 51. Not You 51 © 2010 Howard Lewis Ship
  52. 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. 53. Who Owns Clojure? Rich Hickey 53 © 2010 Howard Lewis Ship
  54. 54. Clojure: written in Clojure 54 © 2010 Howard Lewis Ship
  55. 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. 56. Macros # Special Forms Code Forms Macro Expansion def if let fn . … Bytecode Generation 56 © 2010 Howard Lewis Ship
  57. 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. 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. 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. 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. 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. 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. 63. Wrap Up 63 © 2010 Howard Lewis Ship
  64. 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. 65. Stuart Halloway Pragmatic Bookshelf http://pragprog.com/titles/shcloj/programming-clojure 65 © 2010 Howard Lewis Ship
  66. 66. http://java.ociweb.com/mark/clojure/article.html 66 © 2010 Howard Lewis Ship
  67. 67. http://tapestryjava.blogspot.com 67 © 2010 Howard Lewis Ship
  68. 68. Object Oriented 68 © 2010 Howard Lewis Ship
  69. 69. Functional 69 © 2010 Howard Lewis Ship
  70. 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. 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
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×