Cracking Clojure
Alex Miller
Revelytix
Clojure
• A Lisp on the JVM         (also ClojureScript on JavaScript)

• Dynamic (types, code, etc)
• Functional language
• Compiled (there is no interpreter)
• Immutability and state management
• Code is data
• REPL - Read / Eval / Print / Loop
• Interactive development


                                                                 2
It looks like this...
  (defn neighbors [[x y]]
   (for [dx [-1 0 1]
        dy (if (zero? dx)
           [-1 1]
           [-1 0 1])]
     [(+ dx x) (+ dy y)]))

  (defn live [n alive?]
   (or (= n 3)
      (and (= n 2) alive?)))

  (defn step [world]
   (set
    (for [[cell n] (frequencies (mapcat neighbors world))
         :when (live n (world cell))]
      cell)))

  (defn life [initial-world]
   (iterate step initial-world))
                                                            3
Primitives




             4
Collections




              5
Sequences




            6
Sequences




            6
Functions




            7
Functions




            7
Functions




            7
Compiler




           8
Casting spells




                 9
Creating functions




                     10
Creating functions




                     10
Creating functions




                     10
Creating functions




                     10
Creating functions




                     10
An example...




                11
map




      12
Sequence of lines




                    13
Sequence of files




                    14
Sequence of files




                    14
Sequence functions




                     15
You




      16
Lazy sequences




                 17
18
18
Power




        19
Objects




          20
Maps as cheap objects




                        21
Records




          22
Java
package domain;                                                            	     	     int result = 1;
                                                                           	     	     result = prime *   result + Float.floatToIntBits(alcohol);
public class Beer {                                                        	     	     result = prime *   result + ((beer == null) ? 0 : beer.hashCode());
	     private String beer;                                                 	     	     result = prime *   result + ((brewery == null) ? 0 :
	     private String brewery;                                              brewery.hashCode());
	     private float alcohol;                                               	     	     result = prime *   result + ibu;
	     private int ibu;                                                     	     	     return result;
	                                                                          	     }
	     public Beer(String beer, String brewery, float alcohol, int ibu) {
	     	     super();                                                       	     @Override
	     	     this.beer = beer;                                              	     public boolean equals(Object obj) {
	     	     this.brewery = brewery;                                        	     	     if (this == obj)
	     	     this.alcohol = alcohol;                                        	     	     	     return true;
	     	     this.ibu = ibu;                                                	     	     if (obj == null)
	     }                                                                    	     	     	     return false;
                                                                           	     	     if (getClass() != obj.getClass())
	    public String getBeer() {                                             	     	     	     return false;
	    	     return beer;                                                    	     	     Beer other = (Beer) obj;
	    }                                                                     	     	     if (Float.floatToIntBits(alcohol) != Float
	    public String getBrewery() {                                          	     	     	     	     .floatToIntBits(other.alcohol))
	    	     return brewery;                                                 	     	     	     return false;
	    }                                                                     	     	     if (beer == null) {
	    public float getAlcohol() {                                           	     	     	     if (other.beer != null)
	    	     return alcohol;                                                 	     	     	     	     return false;
	    }                                                                     	     	     } else if (!beer.equals(other.beer))
	    public int getIbu() {                                                 	     	     	     return false;
	    	     return ibu;                                                     	     	     if (brewery == null) {
	    }                                                                     	     	     	     if (other.brewery != null)
	    public void setBeer(String beer) {                                    	     	     	     	     return false;
	    	     this.beer = beer;                                               	     	     } else if (!brewery.equals(other.brewery))
	    }                                                                     	     	     	     return false;
	    public void setBrewery(String brewery) {                              	     	     if (ibu != other.ibu)
	    	     this.brewery = brewery;                                         	     	     	     return false;
	    }                                                                     	     	     return true;
	    public void setAlcohol(float alcohol) {                               	     }
	    	     this.alcohol = alcohol;
	    }                                                                     	     @Override
	    public void setIbu(int ibu) {                                         	     public String toString() {
	    	     this.ibu = ibu;                                                 	     	     return "Beer [beer=" + beer + ", brewery=" + brewery + ",
	    }                                                                     alcohol=" + alcohol + ", ibu=" + ibu + "]";
                                                                           	     }
	    @Override                                                             }
	    public int hashCode() {
	    	     final int prime = 31;                                                                                                                       23
Java
package domain;                                                            	     	     int result = 1;
                                                                           	     	     result = prime *   result + Float.floatToIntBits(alcohol);
public class Beer {                                                        	     	     result = prime *   result + ((beer == null) ? 0 : beer.hashCode());
	     private String beer;                                                 	     	     result = prime *   result + ((brewery == null) ? 0 :
	     private String brewery;                                              brewery.hashCode());
	     private float alcohol;         Fields and types                      	     	     result = prime *   result + ibu;
	
	
      private int ibu;                                                     	
                                                                           	
                                                                                 	
                                                                                 }
                                                                                       return result;                                Hashing
	     public Beer(String beer, String brewery, float alcohol, int ibu) {
	     	     super();                                                       	     @Override
	     	     this.beer = beer;                                              	     public boolean equals(Object obj) {
	
	
      	
      	
            this.brewery = brewery;
            this.alcohol = alcohol;
                                     Construction                          	
                                                                           	
                                                                                 	
                                                                                 	
                                                                                       if (this == obj)
                                                                                       	     return true;

                                                                                                                                     Equality
	     	     this.ibu = ibu;                                                	     	     if (obj == null)
	     }                                                                    	     	     	     return false;
                                                                           	     	     if (getClass() != obj.getClass())
	    public String getBeer() {                                             	     	     	     return false;
	    	     return beer;                                                    	     	     Beer other = (Beer) obj;
	    }                                                                     	     	     if (Float.floatToIntBits(alcohol) != Float
	    public String getBrewery() {                                          	     	     	     	     .floatToIntBits(other.alcohol))
	    	     return brewery;                                                 	     	     	     return false;
	
	
     }
     public float getAlcohol() {       Getters                             	
                                                                           	
                                                                                 	
                                                                                 	
                                                                                       if (beer == null) {
                                                                                       	     if (other.beer != null)
	    	     return alcohol;                                                 	     	     	     	     return false;
	    }                                                                     	     	     } else if (!beer.equals(other.beer))
	    public int getIbu() {                                                 	     	     	     return false;
	    	     return ibu;                                                     	     	     if (brewery == null) {
	    }                                                                     	     	     	     if (other.brewery != null)
	    public void setBeer(String beer) {                                    	     	     	     	     return false;
	    	     this.beer = beer;                                               	     	     } else if (!brewery.equals(other.brewery))
	    }                                                                     	     	     	     return false;
	    public void setBrewery(String brewery) {                              	     	     if (ibu != other.ibu)
	    	     this.brewery = brewery;                                         	     	     	     return false;
	    }                                                                     	     	     return true;
	
	
     public void setAlcohol(float alcohol) {
     	     this.alcohol = alcohol;
                                                    Setters                	     }

	    }                                                                     	     @Override
	    public void setIbu(int ibu) {                                         	     public String toString() {
	    	     this.ibu = ibu;                                                 	     	     return "Beer [beer=" + beer + ", brewery=" + brewery + ",
	    }                                                                     alcohol=" + alcohol + ", ibu=" + ibu + "]";

                                                                                                                                         Printing
                                                                           	     }
	    @Override                                                             }
	    public int hashCode() {
	    	     final int prime = 31;                                                                                                                       23
Data interfaces




                  24
Data interfaces




                  24
Data interfaces




                  25
Data - Clojure vs Java




                         26
Data - Clojure vs Java




                         26
Polymorphism




               27
Generic access FTW




                     28
Multimethods




               29
Multimethod dispatch




                       30
Protocols




            31
State




        32
Atoms




        33
Refs




       34
Agents




         35
Destructuring




                36
for comprehensions




                     37
for comprehensions




                     37
Macros




         38
Macros




         39
Review

            CONCURRENCY          HOST




         DATA             CODE




                                        40
Review

                CONCURRENCY          HOST




         DATA                 CODE



         primitives



                                            40
Review

                CONCURRENCY                HOST




         DATA                       CODE


                      collections
         primitives



                                                  40
Review

                CONCURRENCY                HOST




          sequences




         DATA                       CODE


                      collections
         primitives



                                                  40
Review

                CONCURRENCY                  HOST


             laziness


          sequences




         DATA                         CODE


                        collections
         primitives



                                                    40
Review

                CONCURRENCY                       HOST


             laziness


          sequences
                                      FP




         DATA                              CODE


                        collections
         primitives



                                                         40
Review

                CONCURRENCY                                    HOST


             laziness
                                sequence library

          sequences
                                                   FP




         DATA                                           CODE


                        collections
         primitives



                                                                      40
Review

                  CONCURRENCY                                    HOST


               laziness
                                  sequence library

            sequences
                                                     FP

 records
 types

           DATA                                           CODE


                          collections
           primitives



                                                                        40
Review

                  CONCURRENCY                                    HOST


               laziness
                                  sequence library

            sequences
                                                                        multimethods
                                                     FP
                                                                        protocols

 records
 types

           DATA                                           CODE


                          collections
           primitives



                                                                                   40
Review
        refs    agents
atoms

                             CONCURRENCY                                    HOST
        state

                          laziness
                                             sequence library

                         sequences
                                                                                   multimethods
                                                                FP
                                                                                   protocols

  records
  types

                     DATA                                            CODE


                                     collections
                     primitives



                                                                                              40
Review
        refs    agents
atoms

                             CONCURRENCY                                        HOST
        state

                          laziness
                                             sequence library

                         sequences
                                                                                       multimethods
                                                                 FP
                                                                                       protocols

  records
  types

                     DATA                                                CODE


                                     collections
                     primitives
                                                                destructuring


                                                                                                  40
Review
        refs    agents
atoms

                             CONCURRENCY                                        HOST
        state

                          laziness
                                             sequence library

                         sequences
                                                                                       multimethods
                                                                 FP
                                                                                       protocols

  records
  types

                     DATA                          macros                CODE


                                     collections
                     primitives
                                                                destructuring


                                                                                                  40
Review
         refs      agents
atoms

                                CONCURRENCY                                        HOST
         state

                             laziness
                                                sequence library

                            sequences
                                                                                          multimethods
                                                                    FP
                                                                                          protocols

  records
  types

                        DATA                          macros                CODE


        metadata                        collections
                        primitives
                                                                   destructuring
                                            transients

                                                                                                     40
Review
         refs      agents
atoms

                                CONCURRENCY                                        HOST
         state

                             laziness
                                                sequence library

                            sequences
                                                                                          multimethods
                                                                    FP
                                                                                          protocols

  records
  types

                        DATA                          macros                CODE


        metadata                        collections
                                                                                     namespaces
                        primitives
                                                                   destructuring
                                            transients

                                                                                                     40
Review
         refs      agents
atoms

                                CONCURRENCY                                        HOST
         state

                             laziness
                                                sequence library

                            sequences
                                                                                           multimethods
                                                                    FP
                                                                                           protocols

  records
  types
                                                                                          recursion
                        DATA                          macros                CODE


        metadata                        collections
                                                                                     namespaces
                        primitives
                                                                   destructuring
                                            transients

                                                                                                      40
Review
         refs      agents
atoms

                                CONCURRENCY                                           HOST
         state
                                                                                                    Java libs
                             laziness
                                                sequence library                   Java
                            sequences                                              interop
                                                                                                 multimethods
                                                                    FP
                                                                                                 protocols

  records
  types
                                                                                                recursion
                        DATA                          macros                CODE


        metadata                        collections
                                                                                             namespaces
                        primitives
                                                                   destructuring
                                            transients

                                                                                                                40
Review
                                     futures       promises
         refs      agents
atoms
                                                               pmap
                                CONCURRENCY                                              HOST
         state
                                                                                                       Java libs
                             laziness
                                                  sequence library                    Java
                            sequences                                                 interop
                                                                                                    multimethods
                                                                       FP
                                                                                                    protocols

  records
  types
                                                                                                   recursion
                        DATA                          macros                   CODE


        metadata                        collections
                                                                                                namespaces
                        primitives
                                                                      destructuring
                                               transients

                                                                                                                   40
Conway's Life

   Life's rules:
    If alive and 2 or 3 neighbors Then stay alive   Else die
    If dead and 3 neighbors       Then come to life

                       "Blinker" configuration




   Implementation courtesy of Christophe Grand
   http://clj-me.cgrand.net/2011/08/19/conways-game-of-life/

                                                               41
Thanks!

  • Twitter: @puredanger
  • Blog: http://tech.puredanger.com
  • Work: http://revelytix.com
  • My conferences
    – Strange Loop - http://thestrangeloop.com
    – Clojure/West - http://clojurewest.com

   If you want to pair on Clojure during
   Devoxx, ping me on Twitter!
                                                 43

Cracking clojure

  • 1.
  • 2.
    Clojure • A Lispon the JVM (also ClojureScript on JavaScript) • Dynamic (types, code, etc) • Functional language • Compiled (there is no interpreter) • Immutability and state management • Code is data • REPL - Read / Eval / Print / Loop • Interactive development 2
  • 3.
    It looks likethis... (defn neighbors [[x y]] (for [dx [-1 0 1] dy (if (zero? dx) [-1 1] [-1 0 1])] [(+ dx x) (+ dy y)])) (defn live [n alive?] (or (= n 3) (and (= n 2) alive?))) (defn step [world] (set (for [[cell n] (frequencies (mapcat neighbors world)) :when (live n (world cell))] cell))) (defn life [initial-world] (iterate step initial-world)) 3
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
    map 12
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
    You 16
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
    Maps as cheapobjects 21
  • 31.
  • 32.
    Java package domain; int result = 1; result = prime * result + Float.floatToIntBits(alcohol); public class Beer { result = prime * result + ((beer == null) ? 0 : beer.hashCode()); private String beer; result = prime * result + ((brewery == null) ? 0 : private String brewery; brewery.hashCode()); private float alcohol; result = prime * result + ibu; private int ibu; return result; } public Beer(String beer, String brewery, float alcohol, int ibu) { super(); @Override this.beer = beer; public boolean equals(Object obj) { this.brewery = brewery; if (this == obj) this.alcohol = alcohol; return true; this.ibu = ibu; if (obj == null) } return false; if (getClass() != obj.getClass()) public String getBeer() { return false; return beer; Beer other = (Beer) obj; } if (Float.floatToIntBits(alcohol) != Float public String getBrewery() { .floatToIntBits(other.alcohol)) return brewery; return false; } if (beer == null) { public float getAlcohol() { if (other.beer != null) return alcohol; return false; } } else if (!beer.equals(other.beer)) public int getIbu() { return false; return ibu; if (brewery == null) { } if (other.brewery != null) public void setBeer(String beer) { return false; this.beer = beer; } else if (!brewery.equals(other.brewery)) } return false; public void setBrewery(String brewery) { if (ibu != other.ibu) this.brewery = brewery; return false; } return true; public void setAlcohol(float alcohol) { } this.alcohol = alcohol; } @Override public void setIbu(int ibu) { public String toString() { this.ibu = ibu; return "Beer [beer=" + beer + ", brewery=" + brewery + ", } alcohol=" + alcohol + ", ibu=" + ibu + "]"; } @Override } public int hashCode() { final int prime = 31; 23
  • 33.
    Java package domain; int result = 1; result = prime * result + Float.floatToIntBits(alcohol); public class Beer { result = prime * result + ((beer == null) ? 0 : beer.hashCode()); private String beer; result = prime * result + ((brewery == null) ? 0 : private String brewery; brewery.hashCode()); private float alcohol; Fields and types result = prime * result + ibu; private int ibu; } return result; Hashing public Beer(String beer, String brewery, float alcohol, int ibu) { super(); @Override this.beer = beer; public boolean equals(Object obj) { this.brewery = brewery; this.alcohol = alcohol; Construction if (this == obj) return true; Equality this.ibu = ibu; if (obj == null) } return false; if (getClass() != obj.getClass()) public String getBeer() { return false; return beer; Beer other = (Beer) obj; } if (Float.floatToIntBits(alcohol) != Float public String getBrewery() { .floatToIntBits(other.alcohol)) return brewery; return false; } public float getAlcohol() { Getters if (beer == null) { if (other.beer != null) return alcohol; return false; } } else if (!beer.equals(other.beer)) public int getIbu() { return false; return ibu; if (brewery == null) { } if (other.brewery != null) public void setBeer(String beer) { return false; this.beer = beer; } else if (!brewery.equals(other.brewery)) } return false; public void setBrewery(String brewery) { if (ibu != other.ibu) this.brewery = brewery; return false; } return true; public void setAlcohol(float alcohol) { this.alcohol = alcohol; Setters } } @Override public void setIbu(int ibu) { public String toString() { this.ibu = ibu; return "Beer [beer=" + beer + ", brewery=" + brewery + ", } alcohol=" + alcohol + ", ibu=" + ibu + "]"; Printing } @Override } public int hashCode() { final int prime = 31; 23
  • 34.
  • 35.
  • 36.
  • 37.
    Data - Clojurevs Java 26
  • 38.
    Data - Clojurevs Java 26
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
    Review CONCURRENCY HOST DATA CODE 40
  • 54.
    Review CONCURRENCY HOST DATA CODE primitives 40
  • 55.
    Review CONCURRENCY HOST DATA CODE collections primitives 40
  • 56.
    Review CONCURRENCY HOST sequences DATA CODE collections primitives 40
  • 57.
    Review CONCURRENCY HOST laziness sequences DATA CODE collections primitives 40
  • 58.
    Review CONCURRENCY HOST laziness sequences FP DATA CODE collections primitives 40
  • 59.
    Review CONCURRENCY HOST laziness sequence library sequences FP DATA CODE collections primitives 40
  • 60.
    Review CONCURRENCY HOST laziness sequence library sequences FP records types DATA CODE collections primitives 40
  • 61.
    Review CONCURRENCY HOST laziness sequence library sequences multimethods FP protocols records types DATA CODE collections primitives 40
  • 62.
    Review refs agents atoms CONCURRENCY HOST state laziness sequence library sequences multimethods FP protocols records types DATA CODE collections primitives 40
  • 63.
    Review refs agents atoms CONCURRENCY HOST state laziness sequence library sequences multimethods FP protocols records types DATA CODE collections primitives destructuring 40
  • 64.
    Review refs agents atoms CONCURRENCY HOST state laziness sequence library sequences multimethods FP protocols records types DATA macros CODE collections primitives destructuring 40
  • 65.
    Review refs agents atoms CONCURRENCY HOST state laziness sequence library sequences multimethods FP protocols records types DATA macros CODE metadata collections primitives destructuring transients 40
  • 66.
    Review refs agents atoms CONCURRENCY HOST state laziness sequence library sequences multimethods FP protocols records types DATA macros CODE metadata collections namespaces primitives destructuring transients 40
  • 67.
    Review refs agents atoms CONCURRENCY HOST state laziness sequence library sequences multimethods FP protocols records types recursion DATA macros CODE metadata collections namespaces primitives destructuring transients 40
  • 68.
    Review refs agents atoms CONCURRENCY HOST state Java libs laziness sequence library Java sequences interop multimethods FP protocols records types recursion DATA macros CODE metadata collections namespaces primitives destructuring transients 40
  • 69.
    Review futures promises refs agents atoms pmap CONCURRENCY HOST state Java libs laziness sequence library Java sequences interop multimethods FP protocols records types recursion DATA macros CODE metadata collections namespaces primitives destructuring transients 40
  • 70.
    Conway's Life Life's rules: If alive and 2 or 3 neighbors Then stay alive Else die If dead and 3 neighbors Then come to life "Blinker" configuration Implementation courtesy of Christophe Grand http://clj-me.cgrand.net/2011/08/19/conways-game-of-life/ 41
  • 73.
    Thanks! •Twitter: @puredanger • Blog: http://tech.puredanger.com • Work: http://revelytix.com • My conferences – Strange Loop - http://thestrangeloop.com – Clojure/West - http://clojurewest.com If you want to pair on Clojure during Devoxx, ping me on Twitter! 43