Macros
• Supplied with Clojure, and defined by user
• Argument forms are passed as data to the
    macro function, which returns a new data
    structure as a replacement for the macro call
•   (or x y)
               (let [or__158 x]
• becomes:       (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
    are just macros in Clojure
Macros
• Supplied with Clojure, and defined by user
• Argument forms are passed as data to the
    macro function, which returns a new data
    structure as a replacement for the macro call
•   (or x y)
               (let [or__158 x]
• becomes:       (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
    are just macros in Clojure
Macros
          Java dominance
• Supplied with Clojure, and defined by user
  • State-of-the-artare passed as data to the
• Argument forms     object-oriented
     programming which returns a new data
  macro function,
  • Strong support from the community call
  structure as a replacement for the macro
    • x y)
• (or APIs and libraries for almost anything
••           (let [or__158 x]
  becomes: learn, easy to code
    Easy to
                (if or__158 or__158 y))
  • Really good performance to other languages
• Many things that are ‘built-in’
    •
  are just macros in is close to GNU C++
       Java 7 (server) Clojure
Macros
                    But!
• Supplied with Clojure, and defined by user
• Argument formsthe best paradigm? to the
                    are passed as data
  • Is OOP even which returns a new data
  macro function,
  structure as a replacement for the macro call
  • Concerns about verifiability... and
•     modularity
    (or x y)
               (let [or__158 x]
••    Concurrency model is a bad joke
    becomes:
                 (if or__158 or__158 y))
• • What about the quality of code? languages
  Many things that are ‘built-in’ to other
    are just macros in Clojure
Macros Nouns
    The Kingdom of
• Supplied with Clojure, and defined by user
• Argument forms are passed as data to the
  macro function, which returns a new data
  • Nouns (classes, objects) are first-class call
  structure as a replacement for the macro
      concepts in OOP
•   (or x y)
    • Good for architectural or descriptional
             (let [or__158 x]
• becomes: (if or__158 or__158 y))
      purposes
• Many things that are ‘built-in’ to other languages
    are just macros in Clojure
      http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html
Macros Nouns
    The Kingdom of
• Supplied with Clojure, and defined by user
  • But what formsverbs?passed as data to the
• Argument and functions are dependant on nouns
              about
                    are
      •
      Actions
    macro function, which returns a new data
      • Absurd consequences:
    structure as a replacement for the macro call
•
        package org.apache.catalina;

    (or x y)
        import java.util.concurrent.TimeUnit;


                         (let [or__158 x]
• becomes:
        public interface Executor extends java.util.concurrent.Executor, Lifecycle {
            public String getName();

                           (if or__158 or__158 y))
            void execute(Runnable command, long timeout, TimeUnit unit);



• • “When Verbsthatallowed to exist independently, you
        }

  Many things       are ‘built-in’ to other languages
                are
    are justneed to invent Clojure concepts to hold them”
      don't macros in new Noun
      http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html
Macros Nouns
    The Kingdom of
• Supplied with Clojure, and defined by user
  • But what formsverbs?passed as data to the
• Argument and functions are dependant on nouns
              about
                    are
          InstanceManager instanceManager = ((StandardContext)getParent()).getInstanceManager();
          try {


      •
              servlet = (Servlet) instanceManager.newInstance(servletClass);
      Actions
    macro function, which returns a new data
          } catch (ClassCastException e) {
              unavailable(null);



      • Absurd consequences:
              // Restore the context ClassLoader

    structure as a replacement for the macro call
              throw new ServletException
                  (sm.getString("standardWrapper.notServlet", servletClass), e);
          } catch (Throwable e) {



•
        package = ExceptionUtils.unwrapInvocationTargetException(e);
              e org.apache.catalina;

    (or x y)
              ExceptionUtils.handleThrowable(e);
              unavailable(null);
        import java.util.concurrent.TimeUnit;
              // Added extra log statement for Bugzilla 36630:

                             (let [or__158 x]
• becomes:
              // http://issues.apache.org/bugzilla/show_bug.cgi?id=36630
        public interface Executor extends java.util.concurrent.Executor, Lifecycle {
              if(log.isDebugEnabled()) {
            public String getName();
                  log.debug(sm.getString("standardWrapper.instantiate", servletClass), e);
              }
                               (if or__158 or__158 y))
                void execute(Runnable command, long timeout, TimeUnit unit);



• • “When Verbsthatallowed to exist independently, you
        }

  Many things       are ‘built-in’ to other languages
                 // Restore the context ClassLoader
                 throw new ServletException

                are  (sm.getString("standardWrapper.instantiate", servletClass), e);


    are justneed to invent Clojure concepts to hold them”
      don't macros in new Noun
            }




      http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html
Macros Nouns
    The Kingdom of
• Supplied with Clojure, and defined by user
  • But what formsverbs?passed as data to the
• Argument and functions are dependant on nouns
              about
                    are
          InstanceManager instanceManager = ((StandardContext)getParent()).getInstanceManager();
          try {


      •
          For servlet = of a war, instanceManager.newInstance(servletClass);
              the lack (Servlet)
      Actions
    macro function, which returns a new data
          } catch (ClassCastException e) {
              new ServiceExecutionJoinPoint(
              unavailable(null);
                DistributedQueryAnalyzer.forwardQueryResult(



      • Absurd consequences:
              // Restore the context ClassLoader
                  NotificationSchemaManager.getAbstractSchemaMapper(

    structure as a replacement for the macro call
              throw new ServletException
                    new PublishSubscribeNotificationSchema()).getSchemaProxy().
                  (sm.getString("standardWrapper.notServlet", servletClass), e);
                      executePublishSubscribeQueryPlan(
          } catch (Throwable e) {
                         NotificationSchema.ALERT,



•
        package = ExceptionUtils.unwrapInvocationTargetException(e);
              e org.apache.catalina;
                         new NotificationSchemaPriority(SchemaPriority.MAX_PRIORITY),

    (or x y)
              ExceptionUtils.handleThrowable(e);
                         new PublisherMessage(MessageFactory.getAbstractMessage(
              unavailable(null);
                           MessageType.WRITTEN,
        import java.util.concurrent.TimeUnit;
                           new MessageTransport(MessageTransportType.WOUNDED_SURVIVOR),
              // Added extra log statement for Bugzilla 36630:
                           new MessageSessionDestination(

                          (let [or__158 x]
• becomes:
              // http://issues.apache.org/bugzilla/show_bug.cgi?id=36630
                             DestinationManager.getNullDestinationForQueryPlan()))),
        public interface Executor extends java.util.concurrent.Executor, Lifecycle {
              if(log.isDebugEnabled()) {
                         DistributedWarMachine.getPartyRoleManager().getRegisteredParties(
            public String getName();
                  log.debug(sm.getString("standardWrapper.instantiate", servletClass), e);
                           PartyRoleManager.PARTY_KING ||
              }
                            (if or__158 or__158 y))
                           PartyRoleManager.PARTY_GENERAL ||
            void execute(Runnable command, long timeout, TimeUnit unit);



• • “When Verbsthatallowed to exist independently, you
                           PartyRoleManager.PARTY_AMBASSADOR)).getQueryResult(),
        }

  Many things       are ‘built-in’ to other languages
              // Restore the context ClassLoader
                  PriorityMessageDispatcher.getPriorityDispatchInstance())).
              throw new ServletException
                waitForService();

                are
                  (sm.getString("standardWrapper.instantiate", servletClass), e);


    are justneed to invent Clojure concepts to hold them”
      don't macros in new Noun
          }
          All for the lack of a horseshoe nail.




      http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html
Liskov substitution
                 Macros
          principle (LSP) user
• Supplied with Clojure, and defined by
  • Desirableforms are in theoretical OOP the
• Argument     principle passed as data to
        Let q(x) be a property provable about objects x of type T.
  macro function, which returns a new data
  structure as a where Sprovable for objects y of type S call
                    replacement for. the macro
        Then q(y) should be
                            is a subtype of T

• • Seems to be common sense, right?
  (or x y)
              (let [or__158 x]
••becomes:LSP does not hold...
    When
                 (if or__158 or__158 y))
• •
  Many thingssay weare ‘built-in’ to other languages
      can we that have verifiability?
  are just macros inhave modularity?
       can we say we Clojure
    •
Macros
     A simple (?) example
• Supplied with Clojure, and defined by user
• Argument forms are passed as data to the
    macro function, which returns a new data
    structure as a replacement for the macro call
•   (or x y)
               (let [or__158 x]
• becomes:       (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
    are just macros in Clojure
Macros
          A simple (?) example
   • Supplied with Clojure, and defined by user
public abstract class Shape {
   abstract public double getArea();


   • Argument forms are passed as data to the
   ...
}


       macro function, which returns a new data
public class Rectangle extends Shape {
   // it's dimensions
   private double width, height;

       structure as a replacement for the macro call
   // constructor
   public Rectangle(double width, double height) {
      this.width= width;


   •
      this.height= height;
   }
       (or x y)
   // getters and setters:
   public double getWidth() {

                             (let [or__158 x]
   • becomes:
      return width;
   }
   public double getHeight() {
      return height;
                               (if or__158 or__158 y))
   • Many things that are ‘built-in’ to other languages
   }
   public void setWidth(double width) {
      this.width= width;
   }


   }
       are just macros in Clojure
   public void setHeight(double height) {
      this.height= height;

   // get the area
   public double getArea() {
      return width*height;
   }
}
Macros
          A simple (?) example
   • Supplied with Clojure, and defined by user
public abstract class Shape {
   abstract public double getArea();
                                                     public class Square extends Rectangle {
                                                        // constructor


   • Argument forms are passed as data to the
   ...                                                  public Square(double side) {
}                                                          super(side, side);
                                                        }
                                                        // getters and setters:
       macro function, which returns a new data
public class Rectangle extends Shape {
   // it's dimensions                                   public double getSide() {
   private double width, height;                           return getWidth();

       structure as a replacement for the macro call
   // constructor                                       } // or getHeight()
   public Rectangle(double width, double height) {      public void setSide(double side) {
      this.width= width;                                   super.setWidth(side);
                                                           super.setHeight(side);

   •
      this.height= height;

       (or x y)
   }                                                    }
   // getters and setters:                              public void setWidth(double width) {
   public double getWidth() {                              this.setSide(side);

                             (let [or__158 x]
   • becomes:
      return width;                                     }
   }                                                    public void setHeight(double width) {
   public double getHeight() {                             this.setSide(side);
      return height;
                               (if or__158 or__158 y))  }



   • Many things that are ‘built-in’ to other languages
   }                                                 }
   public void setWidth(double width) {
      this.width= width;
   }


   }
       are just macros in Clojure
   public void setHeight(double height) {
      this.height= height;

   // get the area
   public double getArea() {
      return width*height;
   }
}
Macros
          A simple (?) example
   • Supplied with Clojure, and defined by user
public abstract class Shape {
   abstract public double getArea();
                                                     public class Square extends Rectangle {
                                                        // constructor


   • Argument forms are passed as data to the
   ...                                                  public Square(double side) {
}                                                          super(side, side);
                                                        }
                                                        // getters and setters:
       macro function, which returns a new data
public class Rectangle extends Shape {
   // it's dimensions                                   public double getSide() {
   private double width, height;                           return getWidth();

       structure as a replacement for the macro call
   // constructor                                       } // or getHeight()
   public Rectangle(double width, double height) {      public void setSide(double side) {
      this.width= width;                                   super.setWidth(side);
                                                           super.setHeight(side);

   •
      this.height= height;

       (or x y)
   }                                                    }
   // getters and setters:                              public void setWidth(double width) {
   public double getWidth() {                              this.setSide(side);

                             (let [or__158 x]
   • becomes:
      return width;                                     }
   }                                                    public void setHeight(double width) {
   public double getHeight() {                             this.setSide(side);
      return height;
                               (if or__158 or__158 y))  }



   • Many things that are ‘built-in’ to other languages
   }                                                 }
   public void setWidth(double width) {
      this.width= width;
   }                                          public static void main(String[] args) {


   }
       are just macros in Clojure
   public void setHeight(double height) {
      this.height= height;
                                                 Rectangle r= new Rectangle(1.0, 0.0);
                                                 for (int i= 1; i <= 10; i++) {
                                                    r.setHeight(i);
   // get the area                                  if (r.getArea() != i)
   public double getArea() {                           System.err.println("Error!);
      return width*height;                       }
   }                                          }
}
Macros
          A simple (?) example
   • Supplied with Clojure, and defined by user
public abstract class Shape {
   abstract public double getArea();
                                                     public class Square extends Rectangle {
                                                        // constructor


   • Argument forms are passed as data to the
   ...                                                  public Square(double side) {
}                                                          super(side, side);
                                                        }
                                                        // getters and setters:
       macro function, which returns a new data
public class Rectangle extends Shape {
   // it's dimensions                                   public double getSide() {
   private double width, height;                           return getWidth();

       structure as a replacement for the macro call
   // constructor                                       } // or getHeight()
   public Rectangle(double width, double height) {      public void setSide(double side) {
      this.width= width;                                   super.setWidth(side);
                                                           super.setHeight(side);

   •
      this.height= height;

       (or x y)
   }                                                    }
   // getters and setters:                              public void setWidth(double width) {
   public double getWidth() {                              this.setSide(side);

                             (let [or__158 x]
   • becomes:
      return width;                                     }
   }                                                    public void setHeight(double width) {
   public double getHeight() {                             this.setSide(side);
      return height;
                               (if or__158 or__158 y))  }



   • Many things that are ‘built-in’ to other languages
   }                                                 }
   public void setWidth(double width) {
      this.width= width;
   }


   }
       are just macros in Clojure
   public void setHeight(double height) {
      this.height= height;

   // get the area
   public double getArea() {
      return width*height;
   }
}
Macros
          A simple (?) example
   • Supplied with Clojure, and defined by user
public abstract class Shape {
   abstract public double getArea();
                                                     public class Square extends Rectangle {
                                                        // constructor


   • Argument forms are passed as data to the
   ...                                                  public Square(double side) {
}                                                          super(side, side);
                                                        }
                                                        // getters and setters:
       macro function, which returns a new data
public class Rectangle extends Shape {
   // it's dimensions                                   public double getSide() {
   private double width, height;                           return getWidth();

       structure as a replacement for the macro call
   // constructor                                       } // or getHeight()
   public Rectangle(double width, double height) {      public void setSide(double side) {
      this.width= width;                                   super.setWidth(side);
                                                           super.setHeight(side);

   •
      this.height= height;

       (or x y)
   }                                                    }
   // getters and setters:                              public void setWidth(double width) {
   public double getWidth() {                              this.setSide(side);

                             (let [or__158 x]
   • becomes:
      return width;                                     }
   }                                                    public void setHeight(double width) {
   public double getHeight() {                             this.setSide(side);
      return height;
                               (if or__158 or__158 y))  }



   • Many things that are ‘built-in’ to other languages
   }                                                 }
   public void setWidth(double width) {
      this.width= width;
   }                                          public static void main(String[] args) {


   }
       are just macros in Clojure
   public void setHeight(double height) {
      this.height= height;
                                                 Rectangle r= new Square(1.0);
                                                 for (int i= 1; i <= 10; i++) {
                                                    r.setHeight(i);
   // get the area                                  if (r.getArea() != i)
   public double getArea() {                           System.err.println("Error!);
      return width*height;                       }
   }                                          }
}
Macros LSP!
         Java ignores
• Supplied with Clojure, and defined by user
  • No matter what are code, getArea() will never
• Argumentproperly passed as data to the
            forms  we
    behave
  macro function, which returns a new data
  • Therefore, Square doesn’t pass the Liskov call
  structure as a replacement for the macro
    substitution test
• •
  (or x y)
       “if a derived class doesn't pass this test, it shouldn't
       be a derived class[or__158 x]
                  (let at all”
• becomes:
                     (if or__158 or__158 y))
• •    ... because the resize implementation does not
  Many things that are ‘built-in’ to other languages
       define a mathematical or ontological relation but
  are just macros in Clojure
       rather behavioral
Macrosverifiable
 Java code is not
• Supplied with Clojure, and defined by user
  •
• Argument forms are passed as data to the
        Java does not enforce LSP
    •      Further consequences of noun-verb strong coupling
    macro can not rely on the language returns a new data
      • We function, which to ensure that an inheritance is verifiable
          (nor modular)
    structure as a replacement for the macro call
    • A Java method is not a (mathematical) function
•   (or A method m with a parameter x does not necessarily yield the same
      • x y)
           result, it will depend on
                   (let [or__158 x]
•      •
    becomes:   Global variables

       • Class variables (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
   •
     •         Same (recursively) for any method called inside method m

    are just not can have (untraced) side effects, in many cases the result value
              macros in Clojure
         Methods
         does    matter
Macrosmatter?
    Does it really
• Supplied with Clojure, and defined by user
• Argument forms are passed as data to the
    macro function, which returns a new data
    structure as a replacement for the macro call
•   (or x y)
               (let [or__158 x]
• becomes:       (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
    are just macros in Clojure
Macrosmatter?
    Does it really
• Supplied with Clojure, and defined by user
• • People tend toare passed as data toand
  Argument forms say that verifiability the
    macro function, which returns compatible
       (coding) pragmatics are not a new data
    structure as a replacement for the macro call
•   (or x y)
               (let [or__158 x]
• becomes:       (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
    are just macros in Clojure
Macrosmatter?
    Does it really
• Supplied with Clojure, and defined by user
• • People tend toare passed as data toand
  Argument forms say that verifiability the
    macro function, which returns compatible
       (coding) pragmatics are not a new data
    structure as a replacement for the macro call
    •  Are we really on the good track?
•   (or   x y)
                 (let [or__158 x]
• becomes:         (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
    are just macros in Clojure
Macrosmatter?
   Does it really
• Supplied with Clojure, and defined by user
• • People tend toare passed as data toand
  Argument forms say that verifiability the
  macro function, which returns compatible
     (coding) pragmatics are not a new data
  structure as a replacement for the macro call
  • x y)
     Are we really on the good track?
• (or Agile methodologies: ignore (the big)
    •        (let [or__158 x]
• becomes: as fastor__158 or__158 y))
      problems
                (if
                       as possible

• Many things that are ‘built-in’ to other languages
  are just macros in Clojure
Macrosmatter?
   Does it really
• Supplied with Clojure, and defined by user
• • People tend toare passed as data toand
  Argument forms say that verifiability the
  macro function, which returns compatible
     (coding) pragmatics are not a new data
  structure as a replacement for the macro call
  • x y)
     Are we really on the good track?
• (or Agile methodologies: ignore (the big)
    •         (let [or__158 x]
• becomes: as fastor__158 or__158 y))
      problems
                  (if
                        as possible

• ManyTestas possible on‘built-in’ toproblems as
    • things that are fixing the other languages
      late
           units: rely
  are just macros in Clojure
Macrosmatter?
    Does it really
• Supplied with Clojure, and defined by user
• Argument forms are passed as data to the
    macro function, which returns a new data
    structure as a replacement for the macro call
•   (or x y)
                  (let [or__158 x]
• becomes:          (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
    are just macros in Clojure
        http://www.infoq.com/presentations/Simple-Made-Easy
Macrosmatter?
    Does it really
• Supplied with Clojure, and defined by user
  • What is true of every single bug? to the
• Argument forms are passed as data
    macro function, which returns a new data
    structure as a replacement for the macro call
•   (or x y)
                  (let [or__158 x]
• becomes:          (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
    are just macros in Clojure
        http://www.infoq.com/presentations/Simple-Made-Easy
Macrosmatter?
    Does it really
• Supplied with Clojure, and defined by user
  • What is true of every single bug? to the
• Argumentpassed the compiler and data unit tests
             forms are passed as
      •
      It has                        all the
    macro function, which returns a new data
    structure as a replacement for the macro call
•   (or x y)
                  (let [or__158 x]
• becomes:          (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
    are just macros in Clojure
        http://www.infoq.com/presentations/Simple-Made-Easy
Macrosmatter?
    Does it really
• Supplied with Clojure, and defined by user
  • What is true of every single bug? to the
• Argumentpassed the compiler and data unit tests
             forms are passed as
      •
      It has                        all the
    macro function, which returns a new data
      • However, bugs still exist
    structure as a replacement for the macro call
•   (or x y)
                  (let [or__158 x]
• becomes:          (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
    are just macros in Clojure
        http://www.infoq.com/presentations/Simple-Made-Easy
Macrosmatter?
   Does it really
• Supplied with Clojure, and defined by user
  • What is true of every single bug? to the
• Argumentpassed the compiler and data unit tests
             forms are passed as
    • It has                        all the
  macro function, which returns a new data
    • However, bugs still exist
  structure as a replacement for the macro call
• • As x y) we have strong limitations
  (or humans,
                 (let [or__158 x]
• becomes:         (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
  are just macros in Clojure
       http://www.infoq.com/presentations/Simple-Made-Easy
Macrosmatter?
   Does it really
• Supplied with Clojure, and defined by user
  • What is true of every single bug? to the
• Argumentpassed the compiler and data unit tests
             forms are passed as
    • It has                        all the
  macro function, which returns a new data
    • However, bugs still exist
  structure as a replacement for the macro call
• • As x y) we have strong limitations
  (or humans,
             (let [or__158 x]
    •
• becomes: (if or__158 or__158 y))
      We can only hope to make reliable those things
       we can understand
• Many things that are ‘built-in’ to other languages
  are just macros in Clojure
       http://www.infoq.com/presentations/Simple-Made-Easy
Macrosmatter?
   Does it really
• Supplied with Clojure, and defined by user
  • What is true of every single bug? to the
• Argumentpassed the compiler and data unit tests
             forms are passed as
    • It has                        all the
  macro function, which returns a new data
    • However, bugs still exist
  structure as a replacement for the macro call
• • As x y) we have strong limitations
  (or humans,
             (let [or__158 x]
    •
• becomes: (if or__158 or__158 y))
      We can only hope to make reliable those things
       we can understand
• ManyOur ability to reason about ato other islanguages
   •
       things that are ‘built-in’
                                    program critical
  are justcoding as wellClojure
       to  macros in as to debugging
       http://www.infoq.com/presentations/Simple-Made-Easy
Macros state
     The problem of
• Supplied with Clojure, and defined by user
  • Typical confusion betweenas dataidentity
• Argument forms are passed    value, to the
    and state
    macro function, which returns a new data
      •
    structure as a replacement for the macro call
         Value: something that doesn’t change, e.g.
          Date(09/02/2012), Number(42), etc.
•   (or x y)
    • Identity:(let [or__158 x] associated
• becomes:
                a stable logical entity
          with a series of different values over time
                     (if or__158 or__158 y))
• ManyState: snapshot of‘built-in’ to otheralanguages
   •   things that are the identities on
    are just macros in Clojure
         particular point of time
Macros state
     The problem of
• Supplied with Clojure, and defined by user
• Argument forms areispassed as data to the
    • In OOP, identity state
    macro function, which returns a new data
        • An as a replacement for the macro call
    structure object is a pointer to memory
          containing (only) the current state
•   (or x y)
    • OOP (&(let [or__158 x] the world
               Imperative) manipulate
• becomes: (if or__158 or__158 y))
      directly
• Many things that are ‘built-in’nature languages
      • Objects are mutable by to other
    are just macros in Clojure
Macros
    State and concurrency
• Supplied with Clojure, and defined by user
• Argument forms are passed as data to the
    macro function, which returns a new data
    structure as a replacement for the macro call
•   (or x y)
               (let [or__158 x]
• becomes:       (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
    are just macros in Clojure
Macros
    State and concurrency
• Supplied with Clojure, and defined by user
  • For a coherent system, wepassed as assumptions:
• Argument forms are          need strong
                                          data to the
    macro function, which returns a new data
    structure as a replacement for the macro call
•   (or x y)
                 (let [or__158 x]
• becomes:         (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
    are just macros in Clojure
Macros
    State and concurrency
• Supplied with Clojure, and defined by user
  • For a coherent system, wepassed as assumptions:
• Argument forms are
    •
                              need strong
                                          data to the
        There are no side-effects that touch the state inadvertently
    macro function, which returns a new data
    structure as a replacement for the macro call
•   (or x y)
                   (let [or__158 x]
• becomes:           (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
    are just macros in Clojure
Macros
    State and concurrency
• Supplied with Clojure, and defined by user
  • For a coherent system, wepassed as assumptions:
• Argument forms are
    •
                              need strong
                                          data to the
         There are no side-effects that touch the state inadvertently
    macro function, which returns a new data
      • Multipleas a replacement“polite”the macro call
    structure
                 participants behave in a
                                          for
                                              way


•   (or x y)
                    (let [or__158 x]
• becomes:            (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
    are just macros in Clojure
Macros
    State and concurrency
• Supplied with Clojure, and defined by user
  • For a coherent system, wepassed as assumptions:
• Argument forms are
    •
                              need strong
                                          data to the
          There are no side-effects that touch the state inadvertently
    macro function, which returns a new data
      • Multipleas a replacement“polite”the macro call
    structure
                 participants behave in a
                                          for
                                              way

      •   The world is stopped while we look at or change it
•   (or x y)
                     (let [or__158 x]
• becomes:             (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
    are just macros in Clojure
Macros
   State and concurrency
• Supplied with Clojure, and defined by user
  • For a coherent system, wepassed as assumptions:
• Argument forms are
    •
                              need strong
                                          data to the
          There are no side-effects that touch the state inadvertently
   macro function, which returns a new data
     • Multipleas a replacement“polite”the macro call
   structure
                participants behave in a
                                         for
                                             way

      •   The world is stopped while we look at or change it
• • If the language does not enforce these assumptions... who will?
  (or x y)
                     (let [or__158 x]
• becomes:             (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
   are just macros in Clojure
Macros
   State and concurrency
• Supplied with Clojure, and defined by user
  • For a coherent system, wepassed as assumptions:
• Argument forms are
    •
                              need strong
                                          data to the
          There are no side-effects that touch the state inadvertently
   macro function, which returns a new data
     • Multipleas a replacement“polite”the macro call
   structure
                participants behave in a
                                         for
                                             way

      •   The world is stopped while we look at or change it
• • If the language does not enforce these assumptions... who will?
  (or x y)

•    • Yes, that is (let [or__158 x]designers)
   becomes: us (anybody but the language
                (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
   are just macros in Clojure
Macros
   State and concurrency
• Supplied with Clojure, and defined by user
  • For a coherent system, wepassed as assumptions:
• Argument forms are
    •
                              need strong
                                          data to the
          There are no side-effects that touch the state inadvertently
   macro function, which returns a new data
     • Multipleas a replacement“polite”the macro call
   structure
                participants behave in a
                                         for
                                             way

      •   The world is stopped while we look at or change it
• • If the language does not enforce these assumptions... who will?
  (or x y)
     • Yes, that is (let [or__158 x]designers)
• • There is no way to observe a stable state...
   becomes: us (anybody but the language
                    (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
   are just macros in Clojure
Macros
   State and concurrency
• Supplied with Clojure, and defined by user
  • For a coherent system, wepassed as assumptions:
• Argument forms are
    •
                              need strong
                                          data to the
          There are no side-effects that touch the state inadvertently
   macro function, which returns a new data
     • Multipleas a replacement“polite”the macro call
   structure
                participants behave in a
                                         for
                                             way

      •   The world is stopped while we look at or change it
• • If the language does not enforce these assumptions... who will?
  (or x y)
     • Yes, that is (let [or__158 x]designers)
• • There is no way to observe a stable state...
   becomes: us (anybody but the language
                    (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
    •     Without explicit blocking
   are just macros in Clojure
Macros
   State and concurrency
• Supplied with Clojure, and defined by user
  • For a coherent system, wepassed as assumptions:
• Argument forms are
    •
                              need strong
                                          data to the
          There are no side-effects that touch the state inadvertently
   macro function, which returns a new data
     • Multipleas a replacement“polite”the macro call
   structure
                participants behave in a
                                         for
                                             way

      •   The world is stopped while we look at or change it
• • If the language does not enforce these assumptions... who will?
  (or x y)
     • Yes, that is (let [or__158 x]designers)
• • There is no way to observe a stable state...
   becomes: us (anybody but the language
                    (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
    •     Without explicit blocking
   are just macrosidentities than necessary
     •  Creating more in Clojure
Macros
           Easy != Simple
• Supplied with Clojure, and defined by user
• • Java is easy to learnpassed as data to the
  Argument forms are
  macro has no mechanisms to simplify complexity
          function, which returns a new data
  • But as a replacement for the macro call
  structure
  • In fact, it adds complexity
• (or Most of the standard design patterns exist
        x y)
    •            (let [or__158 x]
• becomes:because they are necessary in OOP [1]
       only
                   (if or__158 or__158 y))
• ManyAlso classescomplexity to otherstate, the
    • things that(nouns), non-verifiability, languages
       syntax add
                      are ‘built-in’
  are just macros in Clojure
        [1] http://www.norvig.com/design-patterns/ppframe.htm
Macros
• Supplied with Clojure, and defined by user
• Argument forms are passed as dataall its
      “Programming, when stripped of to the
    macro function,irrelevancies, boilsnew datano
     circumstantial which returns a down to
    structure as aless than very effectivemacro call
     more and no replacement for the thinking
    so as to avoid unmastered complexity, to very
•   (or x y)
      vigorous separation of your many different
                 (let [or__158 x]
•   becomes:           concerns.”
                (if or__158 or__158 y))
• Many things that are ‘built-in’ to other Dijkstra
                                     - E.W. languages
    are just macros in Clojure
      http://www.cs.utexas.edu/~EWD/transcriptions/EWD05xx/EWD512.html
Macros
• Supplied with Clojure, and defined by user
• Argument forms are passed as data to the
    macro function, which returns a new data
    structure as a replacement for the macro call
•   (or x y)
               (let [or__158 x]
• becomes:       (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
    are just macros in Clojure
Macros
• Supplied with Clojure, and defined by user
• Argument forms are passed as data to the
   "We were after the C++ programmers.
    macro function, which returns a new data
    We managedreplacement for the macro call
    structure as a to drag a lot of them about
                 halfway to Lisp."
•   (or x y)
               (let [or__158 co-author of the Java spec
                       Guy Steele, x]
• becomes:       (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
    are just macros in Clojure
Macros
 Functional Programming
• Supplied with Clojure, and defined by user
  •
• Argument forms are passed as data to the
      Computation as the composition and evaluation of functions
    •    Functions as first-class citizens
    macro function, which returns a new data
    • Side-effects and state are strongly avoided
    structure as thereplacement for the macro call
      •  Functions in a mathematical sense

•   (or • x If y)...) = y once, it will always be the same
               f(x,

        • Caching of results [or__158 x]
                      (let
•   becomes: sequences and lazy evaluation
        • Infinite (if or__158 or__158 y))
      • Immutable structures ‘built-in’ to other languages
•   Many things that are to modify
        • No global variables / state
    are just macros in Clojure
        • Cleaner concurrency
Macros
                    LISP
• Supplied with Clojure, and defined by user
  • LISt Processing are passed as data to the
• ArgumentDiscovered in 1958 by John McCarthy
              forms
  • Created
  macro function, which returns a new data
  • Only FORTRAN is older for the macro call
  structure as a replacement
  • Forxsome time it was the AI language
• (or y)
  • Intended to(letpractical mathematical notation for
• becomes:      be a [or__158 x]
    computer programs or__158 or__158 y))
                 (if
• •
  Many thingsby lambda calculus (Church)
      Inspired that are ‘built-in’ to other languages
  are just macros in Clojure
     • Minimal core
Macros
• Supplied with Clojure, and defined by user
• Argument forms are passed as data to the

•
                      ()
    macro function, which returns a new data
    structure as a replacement for the macro call
    (or x y)
               (let [or__158 x]
• becomes:       (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
    are just macros in Clojure
Macros
 • Supplied with Clojure, and defined by user
 • Argument forms are passed as data to the
(• f ( g a b ) c d )
   macro function, which returns a new data
   structure as a replacement for the macro call
   (or x y)
                (let [or__158 x]
 • becomes:       (if or__158 or__158 y))
 • Many things that are ‘built-in’ to other languages
   are just macros in Clojure
Macros of LISP
   Contributions
• Supplied with Clojure, and defined by user
  • Conditionals are passed as data to the
• • Function asforms
  Argument
                 type
  macro function, which returns a new data
  • Recursionas a replacement for the macro call
  structure
  • Dynamic typing
• (or x y)collection
  • Garbage (let [or__158 x]
• • Nested statements or__158 or__158 y))
  becomes:
                  (if
• • Symbols that are ‘built-in’ to other languages
  Many things
  are just macros in Clojure
  • Data as code
Macros code?
       Is this data or
• Supplied with Clojure, and defined by user
     <project name="MyProject" default="dist" basedir=".">
         <description>
             simple example build file
         </description>


• Argument forms are passed as data to the
       <property name="src" location="src"/>
       <property name="build" location="build"/>
       <property name="dist" location="dist"/>

    macro function, which returns a new data
       <target name="init">
         <tstamp/>

    structure as a replacement for the macro call
         <mkdir dir="${build}"/>
       </target>




•
       <target name="compile" depends="init"

    (or x y) description="compile the source " >
         <javac srcdir="${src}" destdir="${build}"/>
       </target>

                         (let [or__158 x]
• becomes:
       <target name="dist" depends="compile"
             description="generate the distribution" >
                           (if or__158 or__158 y))
         <mkdir dir="${dist}/lib"/>



• Many things that are ‘built-in’ to other languages
         <jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}"/>
       </target>


    are just macros in Clojure
       <target name="clean"
             description="clean up" >
         <delete dir="${build}"/>
         <delete dir="${dist}"/>
       </target>
     </project>
A moment of genius:
                 Macros
                   (eval)defined by user
• Supplied with Clojure, and
•   • McCarthy thought of LISP as just a theoreticaldata to the
    Argument forms are passed as
        to the Turing Machine
                                                    language, an alternative

    macro function,Steve Russell, implemented the (eval) function
    •  One of his students, which returns a new data
    structure as a replacement for the macro call
      • The first LISP interpreter
      • Data y) code, and code became data, homoiconicity: macros!
•   (or x
    •
               became
        LISP hasn’t changed much!
                      (let [or__158 language is not obsolete is that
                                                    x]
•     • “So the
    becomes:short explanation of why this 1950s
                          (if or__158 or__158 y))
        it was not technology but math, and math doesn't get stale.The right thing

• Many things that are ‘built-in’ to other languages
           to compare Lisp to is not 1950s hardware, but, say, the Quicksort algorithm,
           which was discovered in 1960 and is still the fastest general-purpose sort.”
    are just2002, and programming languages have almost caught up with 1958.”
      • “It's macros in Clojure
                     http://www.paulgraham.com/icad.html
Macros
        Language matters
• Supplied with Clojure, and defined by user
• Argument forms are passed as data to the
    macro function, which returns a new data
    structure as a replacement for the macro call
•   (or x y)
                 (let [or__158 x]
• becomes:         (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
    are just macros in Clojure

               http://www.flownet.com/gat/papers/lisp-java.pdf
Macros
• Supplied with Clojure, and defined by user
• Argument forms are passed as data to the
    macro function, which returns a new data
    structure as a replacement for the macro call
•   (or x y)
               (let [or__158 x]
• becomes:       (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
    are just macros in Clojure
Macros
          There is a pattern
• •Supplied with Clojure, and defined by user
                            •
      Increasingly more functional     Gaining popularity

• Argument forms are passed• as data to the
     •
      capabilities
                                           Haskell (e.g. Unreal Engine)
    macro function, which returns a new data
        Perl
                               • Erlang
      • Python
    structure as a replacement •for the macro call
                                  Scheme
      • Ruby
•   (or Groovy
      •
         x y)                    • SBCL
                              • And x]
                (let [or__158 it doesn’t stop there
•   becomes:
      • Scala
      • Clojure
                                 • or__158 library
                  (if or__158 C++0x adds standardy))
•
                                    structures to emulate closures
    Many things that are ‘built-in’ Java 7othertolanguages
                                    to was going include
                                 •
    are just macros in Clojure             closures; they are planned for
                                           Java 8
Macros
                  Why Clojure?
• Supplied with Clojure, and defined by user
  •
• Argument forms are passed as data to the
       LISP (subjective)
    •      Cleaner syntax in constrast with Scala or F#

    macro function, which returns a new data
    • JVM (+ .Net!)
      • Wrapper-free access to and from Java code for the macro call
    structure as a replacement
      • All the Java libraries available
•   • STM x y) Transactional Memory)
    (or (Software
      • Elegant and simple access to shared memory
                         (let [or__158 x]
•   •
    becomes:
       Fast
      • Slower but near the(if languages: C++, C, Java,or__158 y))
                               fastest or__158 Haskell, SBCL

•     • On par with JavaScript
    Many things thatV8are ‘built-in’ to other languages
      • Vastly outperforms Ruby, Python, PHP, Prolog
    are just macros in Clojure liberal licensing
    • Strong community support and open-source
     http://thecleancoder.blogspot.com/2010/08/why-clojure.html
Dynamic development
• REPL - Read-eval-print-loop
• Define functions on the fly
• Load and compile code at runtime
• Introspection
• Interactive environment
Traditional evaluation
Code
Text
       characters
                                                                          Effect

                    Compiler


                               bytecode


                                          Executable
                                                                    JVM
                                           .class/.jar




                                                         Run java
Syntactic Abstraction
Code
Text
       characters
                                                                                    Effect

                      Reader


                                data structures
       characters

                                                   evaluator/
                                                                   bytecode   JVM
                                                    compiler

                               data structures
You
                    Program                      data structures




                                                    Program
                                                    (macro)
Atomic Data Types
• Arbitrary precision integers -12345678987654


• Doubles , BigDecimals
           1.234              1.234M


• Ratios -22/7


• Strings -“fred”, Characters -a b c


• Symbols - fred ethel , Keywords -   :fred :ethel


• Booleans - true false  , Null -
                               nil


• Regex patterns    #“a*b”
Data Structures
• Lists - singly linked, grow at front
  •   (1 2 3 4 5), (fred ethel lucy), (list 1 2 3)


• Vectors - indexed access, grow at end
  •   [1 2 3 4 5], [fred ethel lucy]


• Maps - key/value associations
  •   {:a 1, :b 2, :c 3}, {1 “ethel” 2 “fred”}


• Sets  #{fred ethel lucy}


• Everything Nests
Syntax
• You’ve just seen it
• Data structures are the code
 • Homoiconicity
• No more text-based syntax
• Actually, syntax is in the interpretation of
  data structures
Expressions
• Everything is an expression
• All data literals represent themselves
 • Except:
   • Symbols
      • looks for binding to value, locally,
         then globally
    • Lists
     • An operation form
Operation forms

•   (op ...)

• op can be either:
 • one of very few special ops
 • macro
 • expression which yields a function
Special ops
•   Can have non-normal evaluation of arguments
    •   (def name value-expr)

        •   establishes a global variable
    •   (if test-expr then-expr else-expr)

        •   conditional, evaluates only one of then/
            else
•    fn let loop recur do new . throw try
    set! quote var
Functions
• First-class values
   (def five 5)
   (def sqr (fn [x] (* x x)))
   (sqr five)
   25
• Maps are functions of their keys
   (def m {:fred :ethel :ricky :lucy})
   (m :fred)
   :ethel
Macros
• Supplied with Clojure, and defined by user
• Argument forms are passed as data to the
    macro function, which returns a new data
    structure as a replacement for the macro call
•   (or x y)
               (let [or__158 x]
• becomes:       (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
    are just macros in Clojure
Macros
                  Macros
• Supplied with Clojure, and defined by user
  • Macros receives source code anddata to the
• Argument forms are passed as      returns new
    code, that will compiled
  macro function, which returns a new data
  • Variable as a replacement for the macro call
  structure number of arguments (same as functions)
  • Code y) be generated with list functions, but
           could
• (or x handy to use quasi-quote – ‘ and
    it’s much
               (let [or__158 x]
•   substitution operators – ~ and ~@
  becomes:
                  (if or__158 or__158 y))
• • The # suffix in names is used to generate unique
  Many things that are ‘built-in’ to other languages
    names macroexpand-1 & macroexpand are used
  are just macros in Clojure
    to debug macros
Syntax Summary
• Things that would be declarations, control
  structures, function calls, operators, are all
  just lists with op at front:
          Java                Clojure
  int i = 5;            (def i 5)
  if(x == 0)            (if (zero? x)
    return y;             y
  else                    z)
    return z;
  x* y * z;             (* x y z)
  foo(x, y, z);         (foo x y z)
  foo.bar(x);           (. foo bar x)
Sequences
• Abstraction of traditional Lisp lists
•   (seq coll)

    • if collection is non-empty, return seq
      object on it, else nil
•   (first seq)

    • returns the first element
•   (rest seq)

    • returns a seq of the rest of the elements,
      or nil if no more
Macros
             Lazy Evaluation
• Supplied with Clojure, and defined by user
  • A lazy sequence is aare passed unfolded unless strictly
• Argument forms
    necessary
                         sequence not
                                      as data to the
    macro function, an infinitereturns of 1’s data
      • e.g. (repeat 1) is which sequence a new
    structure as a functions in the standard library are lazy
                        replacement for the macro call
    •  Many sequence
• (or Axlazy function produces a lazy sequence
    •     y)

•   • Benefits (let [or__158 x]
    becomes:
                       (if or__158 or__158 y))
      • Avoidance of unnecessary calculations
•   Many thingsand usage of infinite structures
      •  Creation that are ‘built-in’ to other languages
    are just macros inbe forced if needed
                           Clojure
    • Early evaluation can
Sequence Library
(drop 2 [1 2 3 4 5]) -> (3 4 5)

(take 9 (cycle [1 2 3 4]))
-> (1 2 3 4 1 2 3 4 1)

(interleave [:a :b :c :d :e] [1 2 3 4 5])
-> (:a 1 :b 2 :c 3 :d 4 :e 5)

(partition 3 [1 2 3 4 5 6 7 8 9])
-> ((1 2 3) (4 5 6) (7 8 9))

(map vector [:a :b :c :d :e] [1 2 3 4 5])
-> ([:a 1] [:b 2] [:c 3] [:d 4] [:e 5])

(apply str (interpose , "asdf"))
-> "a,s,d,f"

(reduce + (range 100)) -> 4950
Polymorphism:
                 Macros
           multimethodsby user
• Supplied with Clojure, and defined
  • Multimethods aren’t bound exclusively to types/
• Argument forms are passed as data to the
     classes
  macro function, which returns a new data
  • Dispatching a replacement for the macro call
  structure as   is performed using results of user-
     specified dispatch functions
• (or On y) or more several parameters
    •   x one
                (let [or__158 dispatch−fn) + set of
                                     x]
• becomes: (if or__158
  • Defined as (defmulti func−name or__158 y))
     implementations (via defmethod)
• • You things that are ‘built-in’ relationships with
  Many
        can also define hierarchical
                                    to other languages
  are just macros them in dispatch
    derive, and use in Clojure
Java Interop
(. Math PI)
3.141592653589793

(.. System getProperties (get "java.version"))
"1.5.0_13"

(new java.util.Date)
Thu Jun 05 12:37:32 EDT 2008

(doto (JFrame.) (add (JLabel. "Hello World")) pack show)

;expands to:
(let* [G__1837 (JFrame.)]
   (do (. G__1837 (add (JLabel. "Hello World")))
       (. G__1837 pack)
       (. G__1837 show))
   G__1837)
Java Integration
• Clojure strings are Java Strings, numbers are
  Numbers, collections implement Collection,
  fns implement Callable and Runnable etc.
• Core abstractions, like seq, are Java interfaces
• Clojure seq library works on Java Iterables,
  Strings and arrays.
• Implement and extend Java interfaces and
  classes
• New primitive arithmetic support equals
  Java’s speed.
Swing Example
(import '(javax.swing JFrame JLabel JTextField JButton)
        '(java.awt.event ActionListener) '(java.awt GridLayout))
(defn celsius []
  (let [frame (JFrame. "Celsius Converter")
        temp-text (JTextField.)
        celsius-label (JLabel. "Celsius")
        convert-button (JButton. "Convert")
        fahrenheit-label (JLabel. "Fahrenheit")]
    (.addActionListener convert-button
       (proxy [ActionListener] []
          (actionPerformed [evt]
             (let [c (. Double parseDouble (.getText temp-text))]
               (.setText fahrenheit-label
                  (str (+ 32 (* 1.8 c)) " Fahrenheit"))))))
    (doto frame
      (setLayout (GridLayout. 2 2 3 3))
      (add temp-text) (add celsius-label)
      (add convert-button) (add fahrenheit-label)
      (setSize 300 80) (setVisible true))))
(celsius)
Persistent Data Structures
• Immutable, + old version of the collection is still
  available after 'changes'
• Collection maintains its performance guarantees
  • Therefore new versions are not full copies
• Structural sharing - thread safe, iteration safe
• All Clojure data structures are persistent
  • Hash map/set and vector based upon array
     mapped hash tries (Bagwell)
  • Practical - much faster than O(logN)
Path Copying
                                 HashMap
HashMap
                                 int count    16
int count    15
                                 INode root
INode root
Concurrency
• Interleaved/simultaneous execution
• Must avoid seeing/yielding inconsistent data
• The more components there are to the data,
  the more difficult to keep consistent
• The more steps in a logical change, the more
  difficult to keep consistent
• Opportunities for automatic parallelism
 • Emphasis here on coordination
State - You’re doing it wrong
• Mutable objects are the new spaghetti code
 • Hard to understand, test, reason about
 • Concurrency disaster
 • Terrible default architecture (Java/C#/
    Python/Ruby/Groovy/CLOS...)
• Doing the right thing is very difficult
 • Languages matter!
Typical OO - Direct
references to Mutable Objects
                             foo

                        :a          ?
                        :b          ?
                        :c         42
                        :d          ?
                        :e          6




 • Unifies identity and value
 • Anything can change at any time
 • Consistency is a user problem
Clojure - Indirect references
   to Immutable Objects
              foo                      :a    "fred"
                                       :b   "ethel"
                       @foo            :c      42
                                       :d      17
                                       :e       6




• Separates identity and value
 • Obtaining value requires explicit
   dereference
• Values can never change
 • Never an inconsistent value
Macros
             Parallel execution
• Supplied with Clojure, and defined by user
  •
• Argument forms are passed as data to the
        future
    •       executes given code in separate thread
    macroisfunction, which returns a new data
      • @ used to get results of code execution
      • @ blocks current thread, if results aren’t available yetthe macro call
    structure as a replacement for                               results of code execution
         are cached

    •
•
        promise
    (or isx y)synchronization between parts of programs
      • used for
      • deliver sets value of promise[or__158 x]
                         (let
•   becomes:value, or blocks execution if value isn’t set yet
      • @ reads               (if or__158 or__158 y))
• Many things that are ‘built-in’ to other languages
  •
    •
        pmap, pvalues & pcalls are used for “heavyweight” operations, that could be
        performed in parallel

    are justof macros in how paralellism uses lazy evaluation to work on massive
         Very good explanation on
                                     Clojure
         sets data: http://incanter.org/downloads/fjclj.pdf
Persistent ‘Edit’
                 foo               :a          "fred"
                                   :b         "ethel"
                          @foo     :c            42
                                   :d            17
                                   :e             6


                                        Structural sharing
                                   :a          "lucy"
                                   :b         "ethel"


•
                                   :c            42
    New value is function of old   :d            17


•
                                   :e             6
    Shares immutable structure
•   Doesn’t impede readers
•   Not impeded by readers
Structural Sharing
• Key to efficient ‘copies’ and therefore
  persistence
• Everything is final so no chance of
  interference
• Thread safe
• Iteration safe
Atomic Update
              foo                   :a          "fred"
                                    :b         "ethel"
                                    :c            42
                                    :d            17
                                    :e             6

                       @foo
                                         Structural sharing
                                    :a          "lucy"
                                    :b         "ethel"


• Always coordinated
                                    :c            42
                                    :d            17


 • Multiple semantics
                                    :e             6



• Next dereference sees new value
• Consumers of values unaffected
Clojure References
• The only things that mutate are references
  themselves, in a controlled way
• 3 types of mutable references
 • Vars - Isolate changes within threads
 • Refs - Share synchronous coordinated
    changes between threads
  • Agents - Share asynchronous
    independent changes between threads
Refs and Transactions
• Software transactional memory system (STM)
• Refs can only be changed within a transaction
• All changes are Atomic and Isolated
 • Every change to Refs made within a
    transaction occurs or none do
  • No transaction sees the effects of any
    other transaction while it is running
• Transactions are speculative
 • Will be retried automatically if conflict
 • Must avoid side-effects!
Refs in action
(def foo (ref {:a "fred" :b "ethel" :c 42 :d 17 :e 6}))

@foo -> {:d 17, :a "fred", :b "ethel", :c 42, :e 6}

(assoc @foo :a "lucy")
-> {:d 17, :a "lucy", :b "ethel", :c 42, :e 6}

@foo -> {:d 17, :a "fred", :b "ethel", :c 42, :e 6}

(commute foo assoc :a "lucy")
-> IllegalStateException: No transaction running

(dosync (commute foo assoc :a "lucy"))
@foo -> {:d 17, :a "lucy", :b "ethel", :c 42, :e 6}
Agents
• Manage independent state
• State changes through actions, which are
  ordinary functions (state=>new-state)
• Actions are dispatched using send or send-off,
  which return immediately
• Actions occur asynchronously on thread-pool
  threads
• Only one action per agent happens at a time
Agents
• Agent state always accessible, via deref/@, but
  may not reflect all actions
• Can coordinate with actions using await
• Any dispatches made during an action are held
  until after the state of the agent has changed
• Agents coordinate with transactions - any
  dispatches made during a transaction are held
  until it commits
• Agents are not Actors (Erlang/Scala)
Agents in Action
(def foo (agent {:a "fred" :b "ethel" :c 42 :d 17 :e 6}))

@foo -> {:d 17, :a "fred", :b "ethel", :c 42, :e 6}

(send foo assoc :a "lucy")

@foo -> {:d 17, :a "fred", :b "ethel", :c 42, :e 6}

(await foo)

@foo -> {:d 17, :a "lucy", :b "ethel", :c 42, :e 6}
MacrosClojure
     When to use
• •Supplied with Clojure, and defined by user
• Argument forms are passed as data to the
        Always! Or at least, anything that requires sequence handling:
      •        Data streams
    macro• function, map (pmap) and reduce a new data
             Native parallel which returns

        • Database a replacement for the macro call
    structure ashandling
           • QL for transactional access to SQL through JDBC
•   (or • x Machine learning
             y)
           • clojure.hadoop, incanter (R-like statistical package library)
                      (let [or__158 x]
•   becomes: HTTP, JSON parsing
        • XML,
                           (if or__158 or__158 y))
           • clojure.data.xml, clojure.data.json
• •Many things that are ‘built-in’ to other languages
    •
        Logic programming!

    are just macros indevelopment with a strong focus on performance
         core.logic: project under Clojure
         (~75% faster than Prolog)
Macros
                          Further info
• •Supplied with Clojure, and defined by user
• Argument forms are passed as data to the
         Main sites:
     •       Site of the language – http://clojure.org
     •
    macro#clojure IRC channel at freenode.net returns a new data
             function, which
             Planet Clojure – http://planet.clojure.in
      •  the

    structure projecta(http://github.com/relevance/labrepl) – learning environment call
      • The labrepl as replacement for the macro
      • Try-Clojure (http://www.try-clojure.org/) – you can execute Clojure code via Web-browser
•     • x y)
    (or http://clojuredocs.org/ – documentation and examples
    • Books:
      • Programming Clojure – 2009th,[or__158 x]
                         (let Clojure v. 1.0
•   becomes: The Definitive Guide – 2010th, Clojure, v. 1.2
      • Practical Clojure. (if or__158 or__158 y))

•
      • The Joy of Clojure
    Many things that are ‘built-in’ to other languages
      • Clojure in Action
      • just macros Wikibooks
    are Clojure Notes on RubyLearningClojure
         Clojure Programming on
                                   in
      •
Thanks for your attention!

Clojure: a LISP for the JVM

  • 2.
    Macros • Supplied withClojure, and defined by user • Argument forms are passed as data to the macro function, which returns a new data structure as a replacement for the macro call • (or x y) (let [or__158 x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure
  • 3.
    Macros • Supplied withClojure, and defined by user • Argument forms are passed as data to the macro function, which returns a new data structure as a replacement for the macro call • (or x y) (let [or__158 x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure
  • 4.
    Macros Java dominance • Supplied with Clojure, and defined by user • State-of-the-artare passed as data to the • Argument forms object-oriented programming which returns a new data macro function, • Strong support from the community call structure as a replacement for the macro • x y) • (or APIs and libraries for almost anything •• (let [or__158 x] becomes: learn, easy to code Easy to (if or__158 or__158 y)) • Really good performance to other languages • Many things that are ‘built-in’ • are just macros in is close to GNU C++ Java 7 (server) Clojure
  • 5.
    Macros But! • Supplied with Clojure, and defined by user • Argument formsthe best paradigm? to the are passed as data • Is OOP even which returns a new data macro function, structure as a replacement for the macro call • Concerns about verifiability... and • modularity (or x y) (let [or__158 x] •• Concurrency model is a bad joke becomes: (if or__158 or__158 y)) • • What about the quality of code? languages Many things that are ‘built-in’ to other are just macros in Clojure
  • 6.
    Macros Nouns The Kingdom of • Supplied with Clojure, and defined by user • Argument forms are passed as data to the macro function, which returns a new data • Nouns (classes, objects) are first-class call structure as a replacement for the macro concepts in OOP • (or x y) • Good for architectural or descriptional (let [or__158 x] • becomes: (if or__158 or__158 y)) purposes • Many things that are ‘built-in’ to other languages are just macros in Clojure http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html
  • 7.
    Macros Nouns The Kingdom of • Supplied with Clojure, and defined by user • But what formsverbs?passed as data to the • Argument and functions are dependant on nouns about are • Actions macro function, which returns a new data • Absurd consequences: structure as a replacement for the macro call • package org.apache.catalina; (or x y) import java.util.concurrent.TimeUnit; (let [or__158 x] • becomes: public interface Executor extends java.util.concurrent.Executor, Lifecycle { public String getName(); (if or__158 or__158 y)) void execute(Runnable command, long timeout, TimeUnit unit); • • “When Verbsthatallowed to exist independently, you } Many things are ‘built-in’ to other languages are are justneed to invent Clojure concepts to hold them” don't macros in new Noun http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html
  • 8.
    Macros Nouns The Kingdom of • Supplied with Clojure, and defined by user • But what formsverbs?passed as data to the • Argument and functions are dependant on nouns about are InstanceManager instanceManager = ((StandardContext)getParent()).getInstanceManager(); try { • servlet = (Servlet) instanceManager.newInstance(servletClass); Actions macro function, which returns a new data } catch (ClassCastException e) { unavailable(null); • Absurd consequences: // Restore the context ClassLoader structure as a replacement for the macro call throw new ServletException (sm.getString("standardWrapper.notServlet", servletClass), e); } catch (Throwable e) { • package = ExceptionUtils.unwrapInvocationTargetException(e); e org.apache.catalina; (or x y) ExceptionUtils.handleThrowable(e); unavailable(null); import java.util.concurrent.TimeUnit; // Added extra log statement for Bugzilla 36630: (let [or__158 x] • becomes: // http://issues.apache.org/bugzilla/show_bug.cgi?id=36630 public interface Executor extends java.util.concurrent.Executor, Lifecycle { if(log.isDebugEnabled()) { public String getName(); log.debug(sm.getString("standardWrapper.instantiate", servletClass), e); } (if or__158 or__158 y)) void execute(Runnable command, long timeout, TimeUnit unit); • • “When Verbsthatallowed to exist independently, you } Many things are ‘built-in’ to other languages // Restore the context ClassLoader throw new ServletException are (sm.getString("standardWrapper.instantiate", servletClass), e); are justneed to invent Clojure concepts to hold them” don't macros in new Noun } http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html
  • 9.
    Macros Nouns The Kingdom of • Supplied with Clojure, and defined by user • But what formsverbs?passed as data to the • Argument and functions are dependant on nouns about are InstanceManager instanceManager = ((StandardContext)getParent()).getInstanceManager(); try { • For servlet = of a war, instanceManager.newInstance(servletClass); the lack (Servlet) Actions macro function, which returns a new data } catch (ClassCastException e) { new ServiceExecutionJoinPoint( unavailable(null); DistributedQueryAnalyzer.forwardQueryResult( • Absurd consequences: // Restore the context ClassLoader NotificationSchemaManager.getAbstractSchemaMapper( structure as a replacement for the macro call throw new ServletException new PublishSubscribeNotificationSchema()).getSchemaProxy(). (sm.getString("standardWrapper.notServlet", servletClass), e); executePublishSubscribeQueryPlan( } catch (Throwable e) { NotificationSchema.ALERT, • package = ExceptionUtils.unwrapInvocationTargetException(e); e org.apache.catalina; new NotificationSchemaPriority(SchemaPriority.MAX_PRIORITY), (or x y) ExceptionUtils.handleThrowable(e); new PublisherMessage(MessageFactory.getAbstractMessage( unavailable(null); MessageType.WRITTEN, import java.util.concurrent.TimeUnit; new MessageTransport(MessageTransportType.WOUNDED_SURVIVOR), // Added extra log statement for Bugzilla 36630: new MessageSessionDestination( (let [or__158 x] • becomes: // http://issues.apache.org/bugzilla/show_bug.cgi?id=36630 DestinationManager.getNullDestinationForQueryPlan()))), public interface Executor extends java.util.concurrent.Executor, Lifecycle { if(log.isDebugEnabled()) { DistributedWarMachine.getPartyRoleManager().getRegisteredParties( public String getName(); log.debug(sm.getString("standardWrapper.instantiate", servletClass), e); PartyRoleManager.PARTY_KING || } (if or__158 or__158 y)) PartyRoleManager.PARTY_GENERAL || void execute(Runnable command, long timeout, TimeUnit unit); • • “When Verbsthatallowed to exist independently, you PartyRoleManager.PARTY_AMBASSADOR)).getQueryResult(), } Many things are ‘built-in’ to other languages // Restore the context ClassLoader PriorityMessageDispatcher.getPriorityDispatchInstance())). throw new ServletException waitForService(); are (sm.getString("standardWrapper.instantiate", servletClass), e); are justneed to invent Clojure concepts to hold them” don't macros in new Noun } All for the lack of a horseshoe nail. http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html
  • 10.
    Liskov substitution Macros principle (LSP) user • Supplied with Clojure, and defined by • Desirableforms are in theoretical OOP the • Argument principle passed as data to Let q(x) be a property provable about objects x of type T. macro function, which returns a new data structure as a where Sprovable for objects y of type S call replacement for. the macro Then q(y) should be is a subtype of T • • Seems to be common sense, right? (or x y) (let [or__158 x] ••becomes:LSP does not hold... When (if or__158 or__158 y)) • • Many thingssay weare ‘built-in’ to other languages can we that have verifiability? are just macros inhave modularity? can we say we Clojure •
  • 11.
    Macros A simple (?) example • Supplied with Clojure, and defined by user • Argument forms are passed as data to the macro function, which returns a new data structure as a replacement for the macro call • (or x y) (let [or__158 x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure
  • 12.
    Macros A simple (?) example • Supplied with Clojure, and defined by user public abstract class Shape { abstract public double getArea(); • Argument forms are passed as data to the ... } macro function, which returns a new data public class Rectangle extends Shape { // it's dimensions private double width, height; structure as a replacement for the macro call // constructor public Rectangle(double width, double height) { this.width= width; • this.height= height; } (or x y) // getters and setters: public double getWidth() { (let [or__158 x] • becomes: return width; } public double getHeight() { return height; (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages } public void setWidth(double width) { this.width= width; } } are just macros in Clojure public void setHeight(double height) { this.height= height; // get the area public double getArea() { return width*height; } }
  • 13.
    Macros A simple (?) example • Supplied with Clojure, and defined by user public abstract class Shape { abstract public double getArea(); public class Square extends Rectangle { // constructor • Argument forms are passed as data to the ... public Square(double side) { } super(side, side); } // getters and setters: macro function, which returns a new data public class Rectangle extends Shape { // it's dimensions public double getSide() { private double width, height; return getWidth(); structure as a replacement for the macro call // constructor } // or getHeight() public Rectangle(double width, double height) { public void setSide(double side) { this.width= width; super.setWidth(side); super.setHeight(side); • this.height= height; (or x y) } } // getters and setters: public void setWidth(double width) { public double getWidth() { this.setSide(side); (let [or__158 x] • becomes: return width; } } public void setHeight(double width) { public double getHeight() { this.setSide(side); return height; (if or__158 or__158 y)) } • Many things that are ‘built-in’ to other languages } } public void setWidth(double width) { this.width= width; } } are just macros in Clojure public void setHeight(double height) { this.height= height; // get the area public double getArea() { return width*height; } }
  • 14.
    Macros A simple (?) example • Supplied with Clojure, and defined by user public abstract class Shape { abstract public double getArea(); public class Square extends Rectangle { // constructor • Argument forms are passed as data to the ... public Square(double side) { } super(side, side); } // getters and setters: macro function, which returns a new data public class Rectangle extends Shape { // it's dimensions public double getSide() { private double width, height; return getWidth(); structure as a replacement for the macro call // constructor } // or getHeight() public Rectangle(double width, double height) { public void setSide(double side) { this.width= width; super.setWidth(side); super.setHeight(side); • this.height= height; (or x y) } } // getters and setters: public void setWidth(double width) { public double getWidth() { this.setSide(side); (let [or__158 x] • becomes: return width; } } public void setHeight(double width) { public double getHeight() { this.setSide(side); return height; (if or__158 or__158 y)) } • Many things that are ‘built-in’ to other languages } } public void setWidth(double width) { this.width= width; } public static void main(String[] args) { } are just macros in Clojure public void setHeight(double height) { this.height= height; Rectangle r= new Rectangle(1.0, 0.0); for (int i= 1; i <= 10; i++) { r.setHeight(i); // get the area if (r.getArea() != i) public double getArea() { System.err.println("Error!); return width*height; } } } }
  • 15.
    Macros A simple (?) example • Supplied with Clojure, and defined by user public abstract class Shape { abstract public double getArea(); public class Square extends Rectangle { // constructor • Argument forms are passed as data to the ... public Square(double side) { } super(side, side); } // getters and setters: macro function, which returns a new data public class Rectangle extends Shape { // it's dimensions public double getSide() { private double width, height; return getWidth(); structure as a replacement for the macro call // constructor } // or getHeight() public Rectangle(double width, double height) { public void setSide(double side) { this.width= width; super.setWidth(side); super.setHeight(side); • this.height= height; (or x y) } } // getters and setters: public void setWidth(double width) { public double getWidth() { this.setSide(side); (let [or__158 x] • becomes: return width; } } public void setHeight(double width) { public double getHeight() { this.setSide(side); return height; (if or__158 or__158 y)) } • Many things that are ‘built-in’ to other languages } } public void setWidth(double width) { this.width= width; } } are just macros in Clojure public void setHeight(double height) { this.height= height; // get the area public double getArea() { return width*height; } }
  • 16.
    Macros A simple (?) example • Supplied with Clojure, and defined by user public abstract class Shape { abstract public double getArea(); public class Square extends Rectangle { // constructor • Argument forms are passed as data to the ... public Square(double side) { } super(side, side); } // getters and setters: macro function, which returns a new data public class Rectangle extends Shape { // it's dimensions public double getSide() { private double width, height; return getWidth(); structure as a replacement for the macro call // constructor } // or getHeight() public Rectangle(double width, double height) { public void setSide(double side) { this.width= width; super.setWidth(side); super.setHeight(side); • this.height= height; (or x y) } } // getters and setters: public void setWidth(double width) { public double getWidth() { this.setSide(side); (let [or__158 x] • becomes: return width; } } public void setHeight(double width) { public double getHeight() { this.setSide(side); return height; (if or__158 or__158 y)) } • Many things that are ‘built-in’ to other languages } } public void setWidth(double width) { this.width= width; } public static void main(String[] args) { } are just macros in Clojure public void setHeight(double height) { this.height= height; Rectangle r= new Square(1.0); for (int i= 1; i <= 10; i++) { r.setHeight(i); // get the area if (r.getArea() != i) public double getArea() { System.err.println("Error!); return width*height; } } } }
  • 17.
    Macros LSP! Java ignores • Supplied with Clojure, and defined by user • No matter what are code, getArea() will never • Argumentproperly passed as data to the forms we behave macro function, which returns a new data • Therefore, Square doesn’t pass the Liskov call structure as a replacement for the macro substitution test • • (or x y) “if a derived class doesn't pass this test, it shouldn't be a derived class[or__158 x] (let at all” • becomes: (if or__158 or__158 y)) • • ... because the resize implementation does not Many things that are ‘built-in’ to other languages define a mathematical or ontological relation but are just macros in Clojure rather behavioral
  • 18.
    Macrosverifiable Java codeis not • Supplied with Clojure, and defined by user • • Argument forms are passed as data to the Java does not enforce LSP • Further consequences of noun-verb strong coupling macro can not rely on the language returns a new data • We function, which to ensure that an inheritance is verifiable (nor modular) structure as a replacement for the macro call • A Java method is not a (mathematical) function • (or A method m with a parameter x does not necessarily yield the same • x y) result, it will depend on (let [or__158 x] • • becomes: Global variables • Class variables (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages • • Same (recursively) for any method called inside method m are just not can have (untraced) side effects, in many cases the result value macros in Clojure Methods does matter
  • 19.
    Macrosmatter? Does it really • Supplied with Clojure, and defined by user • Argument forms are passed as data to the macro function, which returns a new data structure as a replacement for the macro call • (or x y) (let [or__158 x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure
  • 20.
    Macrosmatter? Does it really • Supplied with Clojure, and defined by user • • People tend toare passed as data toand Argument forms say that verifiability the macro function, which returns compatible (coding) pragmatics are not a new data structure as a replacement for the macro call • (or x y) (let [or__158 x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure
  • 21.
    Macrosmatter? Does it really • Supplied with Clojure, and defined by user • • People tend toare passed as data toand Argument forms say that verifiability the macro function, which returns compatible (coding) pragmatics are not a new data structure as a replacement for the macro call • Are we really on the good track? • (or x y) (let [or__158 x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure
  • 22.
    Macrosmatter? Does it really • Supplied with Clojure, and defined by user • • People tend toare passed as data toand Argument forms say that verifiability the macro function, which returns compatible (coding) pragmatics are not a new data structure as a replacement for the macro call • x y) Are we really on the good track? • (or Agile methodologies: ignore (the big) • (let [or__158 x] • becomes: as fastor__158 or__158 y)) problems (if as possible • Many things that are ‘built-in’ to other languages are just macros in Clojure
  • 23.
    Macrosmatter? Does it really • Supplied with Clojure, and defined by user • • People tend toare passed as data toand Argument forms say that verifiability the macro function, which returns compatible (coding) pragmatics are not a new data structure as a replacement for the macro call • x y) Are we really on the good track? • (or Agile methodologies: ignore (the big) • (let [or__158 x] • becomes: as fastor__158 or__158 y)) problems (if as possible • ManyTestas possible on‘built-in’ toproblems as • things that are fixing the other languages late units: rely are just macros in Clojure
  • 24.
    Macrosmatter? Does it really • Supplied with Clojure, and defined by user • Argument forms are passed as data to the macro function, which returns a new data structure as a replacement for the macro call • (or x y) (let [or__158 x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure http://www.infoq.com/presentations/Simple-Made-Easy
  • 25.
    Macrosmatter? Does it really • Supplied with Clojure, and defined by user • What is true of every single bug? to the • Argument forms are passed as data macro function, which returns a new data structure as a replacement for the macro call • (or x y) (let [or__158 x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure http://www.infoq.com/presentations/Simple-Made-Easy
  • 26.
    Macrosmatter? Does it really • Supplied with Clojure, and defined by user • What is true of every single bug? to the • Argumentpassed the compiler and data unit tests forms are passed as • It has all the macro function, which returns a new data structure as a replacement for the macro call • (or x y) (let [or__158 x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure http://www.infoq.com/presentations/Simple-Made-Easy
  • 27.
    Macrosmatter? Does it really • Supplied with Clojure, and defined by user • What is true of every single bug? to the • Argumentpassed the compiler and data unit tests forms are passed as • It has all the macro function, which returns a new data • However, bugs still exist structure as a replacement for the macro call • (or x y) (let [or__158 x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure http://www.infoq.com/presentations/Simple-Made-Easy
  • 28.
    Macrosmatter? Does it really • Supplied with Clojure, and defined by user • What is true of every single bug? to the • Argumentpassed the compiler and data unit tests forms are passed as • It has all the macro function, which returns a new data • However, bugs still exist structure as a replacement for the macro call • • As x y) we have strong limitations (or humans, (let [or__158 x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure http://www.infoq.com/presentations/Simple-Made-Easy
  • 29.
    Macrosmatter? Does it really • Supplied with Clojure, and defined by user • What is true of every single bug? to the • Argumentpassed the compiler and data unit tests forms are passed as • It has all the macro function, which returns a new data • However, bugs still exist structure as a replacement for the macro call • • As x y) we have strong limitations (or humans, (let [or__158 x] • • becomes: (if or__158 or__158 y)) We can only hope to make reliable those things we can understand • Many things that are ‘built-in’ to other languages are just macros in Clojure http://www.infoq.com/presentations/Simple-Made-Easy
  • 30.
    Macrosmatter? Does it really • Supplied with Clojure, and defined by user • What is true of every single bug? to the • Argumentpassed the compiler and data unit tests forms are passed as • It has all the macro function, which returns a new data • However, bugs still exist structure as a replacement for the macro call • • As x y) we have strong limitations (or humans, (let [or__158 x] • • becomes: (if or__158 or__158 y)) We can only hope to make reliable those things we can understand • ManyOur ability to reason about ato other islanguages • things that are ‘built-in’ program critical are justcoding as wellClojure to macros in as to debugging http://www.infoq.com/presentations/Simple-Made-Easy
  • 31.
    Macros state The problem of • Supplied with Clojure, and defined by user • Typical confusion betweenas dataidentity • Argument forms are passed value, to the and state macro function, which returns a new data • structure as a replacement for the macro call Value: something that doesn’t change, e.g. Date(09/02/2012), Number(42), etc. • (or x y) • Identity:(let [or__158 x] associated • becomes: a stable logical entity with a series of different values over time (if or__158 or__158 y)) • ManyState: snapshot of‘built-in’ to otheralanguages • things that are the identities on are just macros in Clojure particular point of time
  • 32.
    Macros state The problem of • Supplied with Clojure, and defined by user • Argument forms areispassed as data to the • In OOP, identity state macro function, which returns a new data • An as a replacement for the macro call structure object is a pointer to memory containing (only) the current state • (or x y) • OOP (&(let [or__158 x] the world Imperative) manipulate • becomes: (if or__158 or__158 y)) directly • Many things that are ‘built-in’nature languages • Objects are mutable by to other are just macros in Clojure
  • 33.
    Macros State and concurrency • Supplied with Clojure, and defined by user • Argument forms are passed as data to the macro function, which returns a new data structure as a replacement for the macro call • (or x y) (let [or__158 x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure
  • 34.
    Macros State and concurrency • Supplied with Clojure, and defined by user • For a coherent system, wepassed as assumptions: • Argument forms are need strong data to the macro function, which returns a new data structure as a replacement for the macro call • (or x y) (let [or__158 x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure
  • 35.
    Macros State and concurrency • Supplied with Clojure, and defined by user • For a coherent system, wepassed as assumptions: • Argument forms are • need strong data to the There are no side-effects that touch the state inadvertently macro function, which returns a new data structure as a replacement for the macro call • (or x y) (let [or__158 x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure
  • 36.
    Macros State and concurrency • Supplied with Clojure, and defined by user • For a coherent system, wepassed as assumptions: • Argument forms are • need strong data to the There are no side-effects that touch the state inadvertently macro function, which returns a new data • Multipleas a replacement“polite”the macro call structure participants behave in a for way • (or x y) (let [or__158 x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure
  • 37.
    Macros State and concurrency • Supplied with Clojure, and defined by user • For a coherent system, wepassed as assumptions: • Argument forms are • need strong data to the There are no side-effects that touch the state inadvertently macro function, which returns a new data • Multipleas a replacement“polite”the macro call structure participants behave in a for way • The world is stopped while we look at or change it • (or x y) (let [or__158 x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure
  • 38.
    Macros State and concurrency • Supplied with Clojure, and defined by user • For a coherent system, wepassed as assumptions: • Argument forms are • need strong data to the There are no side-effects that touch the state inadvertently macro function, which returns a new data • Multipleas a replacement“polite”the macro call structure participants behave in a for way • The world is stopped while we look at or change it • • If the language does not enforce these assumptions... who will? (or x y) (let [or__158 x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure
  • 39.
    Macros State and concurrency • Supplied with Clojure, and defined by user • For a coherent system, wepassed as assumptions: • Argument forms are • need strong data to the There are no side-effects that touch the state inadvertently macro function, which returns a new data • Multipleas a replacement“polite”the macro call structure participants behave in a for way • The world is stopped while we look at or change it • • If the language does not enforce these assumptions... who will? (or x y) • • Yes, that is (let [or__158 x]designers) becomes: us (anybody but the language (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure
  • 40.
    Macros State and concurrency • Supplied with Clojure, and defined by user • For a coherent system, wepassed as assumptions: • Argument forms are • need strong data to the There are no side-effects that touch the state inadvertently macro function, which returns a new data • Multipleas a replacement“polite”the macro call structure participants behave in a for way • The world is stopped while we look at or change it • • If the language does not enforce these assumptions... who will? (or x y) • Yes, that is (let [or__158 x]designers) • • There is no way to observe a stable state... becomes: us (anybody but the language (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure
  • 41.
    Macros State and concurrency • Supplied with Clojure, and defined by user • For a coherent system, wepassed as assumptions: • Argument forms are • need strong data to the There are no side-effects that touch the state inadvertently macro function, which returns a new data • Multipleas a replacement“polite”the macro call structure participants behave in a for way • The world is stopped while we look at or change it • • If the language does not enforce these assumptions... who will? (or x y) • Yes, that is (let [or__158 x]designers) • • There is no way to observe a stable state... becomes: us (anybody but the language (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages • Without explicit blocking are just macros in Clojure
  • 42.
    Macros State and concurrency • Supplied with Clojure, and defined by user • For a coherent system, wepassed as assumptions: • Argument forms are • need strong data to the There are no side-effects that touch the state inadvertently macro function, which returns a new data • Multipleas a replacement“polite”the macro call structure participants behave in a for way • The world is stopped while we look at or change it • • If the language does not enforce these assumptions... who will? (or x y) • Yes, that is (let [or__158 x]designers) • • There is no way to observe a stable state... becomes: us (anybody but the language (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages • Without explicit blocking are just macrosidentities than necessary • Creating more in Clojure
  • 43.
    Macros Easy != Simple • Supplied with Clojure, and defined by user • • Java is easy to learnpassed as data to the Argument forms are macro has no mechanisms to simplify complexity function, which returns a new data • But as a replacement for the macro call structure • In fact, it adds complexity • (or Most of the standard design patterns exist x y) • (let [or__158 x] • becomes:because they are necessary in OOP [1] only (if or__158 or__158 y)) • ManyAlso classescomplexity to otherstate, the • things that(nouns), non-verifiability, languages syntax add are ‘built-in’ are just macros in Clojure [1] http://www.norvig.com/design-patterns/ppframe.htm
  • 44.
    Macros • Supplied withClojure, and defined by user • Argument forms are passed as dataall its “Programming, when stripped of to the macro function,irrelevancies, boilsnew datano circumstantial which returns a down to structure as aless than very effectivemacro call more and no replacement for the thinking so as to avoid unmastered complexity, to very • (or x y) vigorous separation of your many different (let [or__158 x] • becomes: concerns.” (if or__158 or__158 y)) • Many things that are ‘built-in’ to other Dijkstra - E.W. languages are just macros in Clojure http://www.cs.utexas.edu/~EWD/transcriptions/EWD05xx/EWD512.html
  • 45.
    Macros • Supplied withClojure, and defined by user • Argument forms are passed as data to the macro function, which returns a new data structure as a replacement for the macro call • (or x y) (let [or__158 x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure
  • 46.
    Macros • Supplied withClojure, and defined by user • Argument forms are passed as data to the "We were after the C++ programmers. macro function, which returns a new data We managedreplacement for the macro call structure as a to drag a lot of them about halfway to Lisp." • (or x y) (let [or__158 co-author of the Java spec Guy Steele, x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure
  • 47.
    Macros Functional Programming •Supplied with Clojure, and defined by user • • Argument forms are passed as data to the Computation as the composition and evaluation of functions • Functions as first-class citizens macro function, which returns a new data • Side-effects and state are strongly avoided structure as thereplacement for the macro call • Functions in a mathematical sense • (or • x If y)...) = y once, it will always be the same f(x, • Caching of results [or__158 x] (let • becomes: sequences and lazy evaluation • Infinite (if or__158 or__158 y)) • Immutable structures ‘built-in’ to other languages • Many things that are to modify • No global variables / state are just macros in Clojure • Cleaner concurrency
  • 48.
    Macros LISP • Supplied with Clojure, and defined by user • LISt Processing are passed as data to the • ArgumentDiscovered in 1958 by John McCarthy forms • Created macro function, which returns a new data • Only FORTRAN is older for the macro call structure as a replacement • Forxsome time it was the AI language • (or y) • Intended to(letpractical mathematical notation for • becomes: be a [or__158 x] computer programs or__158 or__158 y)) (if • • Many thingsby lambda calculus (Church) Inspired that are ‘built-in’ to other languages are just macros in Clojure • Minimal core
  • 49.
    Macros • Supplied withClojure, and defined by user • Argument forms are passed as data to the • () macro function, which returns a new data structure as a replacement for the macro call (or x y) (let [or__158 x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure
  • 50.
    Macros • Suppliedwith Clojure, and defined by user • Argument forms are passed as data to the (• f ( g a b ) c d ) macro function, which returns a new data structure as a replacement for the macro call (or x y) (let [or__158 x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure
  • 51.
    Macros of LISP Contributions • Supplied with Clojure, and defined by user • Conditionals are passed as data to the • • Function asforms Argument type macro function, which returns a new data • Recursionas a replacement for the macro call structure • Dynamic typing • (or x y)collection • Garbage (let [or__158 x] • • Nested statements or__158 or__158 y)) becomes: (if • • Symbols that are ‘built-in’ to other languages Many things are just macros in Clojure • Data as code
  • 52.
    Macros code? Is this data or • Supplied with Clojure, and defined by user <project name="MyProject" default="dist" basedir="."> <description> simple example build file </description> • Argument forms are passed as data to the <property name="src" location="src"/> <property name="build" location="build"/> <property name="dist" location="dist"/> macro function, which returns a new data <target name="init"> <tstamp/> structure as a replacement for the macro call <mkdir dir="${build}"/> </target> • <target name="compile" depends="init" (or x y) description="compile the source " > <javac srcdir="${src}" destdir="${build}"/> </target> (let [or__158 x] • becomes: <target name="dist" depends="compile" description="generate the distribution" > (if or__158 or__158 y)) <mkdir dir="${dist}/lib"/> • Many things that are ‘built-in’ to other languages <jar jarfile="${dist}/lib/MyProject-${DSTAMP}.jar" basedir="${build}"/> </target> are just macros in Clojure <target name="clean" description="clean up" > <delete dir="${build}"/> <delete dir="${dist}"/> </target> </project>
  • 53.
    A moment ofgenius: Macros (eval)defined by user • Supplied with Clojure, and • • McCarthy thought of LISP as just a theoreticaldata to the Argument forms are passed as to the Turing Machine language, an alternative macro function,Steve Russell, implemented the (eval) function • One of his students, which returns a new data structure as a replacement for the macro call • The first LISP interpreter • Data y) code, and code became data, homoiconicity: macros! • (or x • became LISP hasn’t changed much! (let [or__158 language is not obsolete is that x] • • “So the becomes:short explanation of why this 1950s (if or__158 or__158 y)) it was not technology but math, and math doesn't get stale.The right thing • Many things that are ‘built-in’ to other languages to compare Lisp to is not 1950s hardware, but, say, the Quicksort algorithm, which was discovered in 1960 and is still the fastest general-purpose sort.” are just2002, and programming languages have almost caught up with 1958.” • “It's macros in Clojure http://www.paulgraham.com/icad.html
  • 54.
    Macros Language matters • Supplied with Clojure, and defined by user • Argument forms are passed as data to the macro function, which returns a new data structure as a replacement for the macro call • (or x y) (let [or__158 x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure http://www.flownet.com/gat/papers/lisp-java.pdf
  • 55.
    Macros • Supplied withClojure, and defined by user • Argument forms are passed as data to the macro function, which returns a new data structure as a replacement for the macro call • (or x y) (let [or__158 x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure
  • 56.
    Macros There is a pattern • •Supplied with Clojure, and defined by user • Increasingly more functional Gaining popularity • Argument forms are passed• as data to the • capabilities Haskell (e.g. Unreal Engine) macro function, which returns a new data Perl • Erlang • Python structure as a replacement •for the macro call Scheme • Ruby • (or Groovy • x y) • SBCL • And x] (let [or__158 it doesn’t stop there • becomes: • Scala • Clojure • or__158 library (if or__158 C++0x adds standardy)) • structures to emulate closures Many things that are ‘built-in’ Java 7othertolanguages to was going include • are just macros in Clojure closures; they are planned for Java 8
  • 57.
    Macros Why Clojure? • Supplied with Clojure, and defined by user • • Argument forms are passed as data to the LISP (subjective) • Cleaner syntax in constrast with Scala or F# macro function, which returns a new data • JVM (+ .Net!) • Wrapper-free access to and from Java code for the macro call structure as a replacement • All the Java libraries available • • STM x y) Transactional Memory) (or (Software • Elegant and simple access to shared memory (let [or__158 x] • • becomes: Fast • Slower but near the(if languages: C++, C, Java,or__158 y)) fastest or__158 Haskell, SBCL • • On par with JavaScript Many things thatV8are ‘built-in’ to other languages • Vastly outperforms Ruby, Python, PHP, Prolog are just macros in Clojure liberal licensing • Strong community support and open-source http://thecleancoder.blogspot.com/2010/08/why-clojure.html
  • 58.
    Dynamic development • REPL- Read-eval-print-loop • Define functions on the fly • Load and compile code at runtime • Introspection • Interactive environment
  • 59.
    Traditional evaluation Code Text characters Effect Compiler bytecode Executable JVM .class/.jar Run java
  • 60.
    Syntactic Abstraction Code Text characters Effect Reader data structures characters evaluator/ bytecode JVM compiler data structures You Program data structures Program (macro)
  • 61.
    Atomic Data Types •Arbitrary precision integers -12345678987654 • Doubles , BigDecimals 1.234 1.234M • Ratios -22/7 • Strings -“fred”, Characters -a b c • Symbols - fred ethel , Keywords - :fred :ethel • Booleans - true false , Null - nil • Regex patterns #“a*b”
  • 62.
    Data Structures • Lists- singly linked, grow at front • (1 2 3 4 5), (fred ethel lucy), (list 1 2 3) • Vectors - indexed access, grow at end • [1 2 3 4 5], [fred ethel lucy] • Maps - key/value associations • {:a 1, :b 2, :c 3}, {1 “ethel” 2 “fred”} • Sets #{fred ethel lucy} • Everything Nests
  • 63.
    Syntax • You’ve justseen it • Data structures are the code • Homoiconicity • No more text-based syntax • Actually, syntax is in the interpretation of data structures
  • 64.
    Expressions • Everything isan expression • All data literals represent themselves • Except: • Symbols • looks for binding to value, locally, then globally • Lists • An operation form
  • 65.
    Operation forms • (op ...) • op can be either: • one of very few special ops • macro • expression which yields a function
  • 66.
    Special ops • Can have non-normal evaluation of arguments • (def name value-expr) • establishes a global variable • (if test-expr then-expr else-expr) • conditional, evaluates only one of then/ else • fn let loop recur do new . throw try set! quote var
  • 67.
    Functions • First-class values (def five 5) (def sqr (fn [x] (* x x))) (sqr five) 25 • Maps are functions of their keys (def m {:fred :ethel :ricky :lucy}) (m :fred) :ethel
  • 68.
    Macros • Supplied withClojure, and defined by user • Argument forms are passed as data to the macro function, which returns a new data structure as a replacement for the macro call • (or x y) (let [or__158 x] • becomes: (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages are just macros in Clojure
  • 69.
    Macros Macros • Supplied with Clojure, and defined by user • Macros receives source code anddata to the • Argument forms are passed as returns new code, that will compiled macro function, which returns a new data • Variable as a replacement for the macro call structure number of arguments (same as functions) • Code y) be generated with list functions, but could • (or x handy to use quasi-quote – ‘ and it’s much (let [or__158 x] • substitution operators – ~ and ~@ becomes: (if or__158 or__158 y)) • • The # suffix in names is used to generate unique Many things that are ‘built-in’ to other languages names macroexpand-1 & macroexpand are used are just macros in Clojure to debug macros
  • 70.
    Syntax Summary • Thingsthat would be declarations, control structures, function calls, operators, are all just lists with op at front: Java Clojure int i = 5; (def i 5) if(x == 0) (if (zero? x) return y; y else z) return z; x* y * z; (* x y z) foo(x, y, z); (foo x y z) foo.bar(x); (. foo bar x)
  • 71.
    Sequences • Abstraction oftraditional Lisp lists • (seq coll) • if collection is non-empty, return seq object on it, else nil • (first seq) • returns the first element • (rest seq) • returns a seq of the rest of the elements, or nil if no more
  • 72.
    Macros Lazy Evaluation • Supplied with Clojure, and defined by user • A lazy sequence is aare passed unfolded unless strictly • Argument forms necessary sequence not as data to the macro function, an infinitereturns of 1’s data • e.g. (repeat 1) is which sequence a new structure as a functions in the standard library are lazy replacement for the macro call • Many sequence • (or Axlazy function produces a lazy sequence • y) • • Benefits (let [or__158 x] becomes: (if or__158 or__158 y)) • Avoidance of unnecessary calculations • Many thingsand usage of infinite structures • Creation that are ‘built-in’ to other languages are just macros inbe forced if needed Clojure • Early evaluation can
  • 73.
    Sequence Library (drop 2[1 2 3 4 5]) -> (3 4 5) (take 9 (cycle [1 2 3 4])) -> (1 2 3 4 1 2 3 4 1) (interleave [:a :b :c :d :e] [1 2 3 4 5]) -> (:a 1 :b 2 :c 3 :d 4 :e 5) (partition 3 [1 2 3 4 5 6 7 8 9]) -> ((1 2 3) (4 5 6) (7 8 9)) (map vector [:a :b :c :d :e] [1 2 3 4 5]) -> ([:a 1] [:b 2] [:c 3] [:d 4] [:e 5]) (apply str (interpose , "asdf")) -> "a,s,d,f" (reduce + (range 100)) -> 4950
  • 74.
    Polymorphism: Macros multimethodsby user • Supplied with Clojure, and defined • Multimethods aren’t bound exclusively to types/ • Argument forms are passed as data to the classes macro function, which returns a new data • Dispatching a replacement for the macro call structure as is performed using results of user- specified dispatch functions • (or On y) or more several parameters • x one (let [or__158 dispatch−fn) + set of x] • becomes: (if or__158 • Defined as (defmulti func−name or__158 y)) implementations (via defmethod) • • You things that are ‘built-in’ relationships with Many can also define hierarchical to other languages are just macros them in dispatch derive, and use in Clojure
  • 75.
    Java Interop (. MathPI) 3.141592653589793 (.. System getProperties (get "java.version")) "1.5.0_13" (new java.util.Date) Thu Jun 05 12:37:32 EDT 2008 (doto (JFrame.) (add (JLabel. "Hello World")) pack show) ;expands to: (let* [G__1837 (JFrame.)] (do (. G__1837 (add (JLabel. "Hello World"))) (. G__1837 pack) (. G__1837 show)) G__1837)
  • 76.
    Java Integration • Clojurestrings are Java Strings, numbers are Numbers, collections implement Collection, fns implement Callable and Runnable etc. • Core abstractions, like seq, are Java interfaces • Clojure seq library works on Java Iterables, Strings and arrays. • Implement and extend Java interfaces and classes • New primitive arithmetic support equals Java’s speed.
  • 77.
    Swing Example (import '(javax.swingJFrame JLabel JTextField JButton) '(java.awt.event ActionListener) '(java.awt GridLayout)) (defn celsius [] (let [frame (JFrame. "Celsius Converter") temp-text (JTextField.) celsius-label (JLabel. "Celsius") convert-button (JButton. "Convert") fahrenheit-label (JLabel. "Fahrenheit")] (.addActionListener convert-button (proxy [ActionListener] [] (actionPerformed [evt] (let [c (. Double parseDouble (.getText temp-text))] (.setText fahrenheit-label (str (+ 32 (* 1.8 c)) " Fahrenheit")))))) (doto frame (setLayout (GridLayout. 2 2 3 3)) (add temp-text) (add celsius-label) (add convert-button) (add fahrenheit-label) (setSize 300 80) (setVisible true)))) (celsius)
  • 78.
    Persistent Data Structures •Immutable, + old version of the collection is still available after 'changes' • Collection maintains its performance guarantees • Therefore new versions are not full copies • Structural sharing - thread safe, iteration safe • All Clojure data structures are persistent • Hash map/set and vector based upon array mapped hash tries (Bagwell) • Practical - much faster than O(logN)
  • 79.
    Path Copying HashMap HashMap int count 16 int count 15 INode root INode root
  • 80.
    Concurrency • Interleaved/simultaneous execution •Must avoid seeing/yielding inconsistent data • The more components there are to the data, the more difficult to keep consistent • The more steps in a logical change, the more difficult to keep consistent • Opportunities for automatic parallelism • Emphasis here on coordination
  • 81.
    State - You’redoing it wrong • Mutable objects are the new spaghetti code • Hard to understand, test, reason about • Concurrency disaster • Terrible default architecture (Java/C#/ Python/Ruby/Groovy/CLOS...) • Doing the right thing is very difficult • Languages matter!
  • 82.
    Typical OO -Direct references to Mutable Objects foo :a ? :b ? :c 42 :d ? :e 6 • Unifies identity and value • Anything can change at any time • Consistency is a user problem
  • 83.
    Clojure - Indirectreferences to Immutable Objects foo :a "fred" :b "ethel" @foo :c 42 :d 17 :e 6 • Separates identity and value • Obtaining value requires explicit dereference • Values can never change • Never an inconsistent value
  • 84.
    Macros Parallel execution • Supplied with Clojure, and defined by user • • Argument forms are passed as data to the future • executes given code in separate thread macroisfunction, which returns a new data • @ used to get results of code execution • @ blocks current thread, if results aren’t available yetthe macro call structure as a replacement for results of code execution are cached • • promise (or isx y)synchronization between parts of programs • used for • deliver sets value of promise[or__158 x] (let • becomes:value, or blocks execution if value isn’t set yet • @ reads (if or__158 or__158 y)) • Many things that are ‘built-in’ to other languages • • pmap, pvalues & pcalls are used for “heavyweight” operations, that could be performed in parallel are justof macros in how paralellism uses lazy evaluation to work on massive Very good explanation on Clojure sets data: http://incanter.org/downloads/fjclj.pdf
  • 85.
    Persistent ‘Edit’ foo :a "fred" :b "ethel" @foo :c 42 :d 17 :e 6 Structural sharing :a "lucy" :b "ethel" • :c 42 New value is function of old :d 17 • :e 6 Shares immutable structure • Doesn’t impede readers • Not impeded by readers
  • 86.
    Structural Sharing • Keyto efficient ‘copies’ and therefore persistence • Everything is final so no chance of interference • Thread safe • Iteration safe
  • 87.
    Atomic Update foo :a "fred" :b "ethel" :c 42 :d 17 :e 6 @foo Structural sharing :a "lucy" :b "ethel" • Always coordinated :c 42 :d 17 • Multiple semantics :e 6 • Next dereference sees new value • Consumers of values unaffected
  • 88.
    Clojure References • Theonly things that mutate are references themselves, in a controlled way • 3 types of mutable references • Vars - Isolate changes within threads • Refs - Share synchronous coordinated changes between threads • Agents - Share asynchronous independent changes between threads
  • 89.
    Refs and Transactions •Software transactional memory system (STM) • Refs can only be changed within a transaction • All changes are Atomic and Isolated • Every change to Refs made within a transaction occurs or none do • No transaction sees the effects of any other transaction while it is running • Transactions are speculative • Will be retried automatically if conflict • Must avoid side-effects!
  • 90.
    Refs in action (deffoo (ref {:a "fred" :b "ethel" :c 42 :d 17 :e 6})) @foo -> {:d 17, :a "fred", :b "ethel", :c 42, :e 6} (assoc @foo :a "lucy") -> {:d 17, :a "lucy", :b "ethel", :c 42, :e 6} @foo -> {:d 17, :a "fred", :b "ethel", :c 42, :e 6} (commute foo assoc :a "lucy") -> IllegalStateException: No transaction running (dosync (commute foo assoc :a "lucy")) @foo -> {:d 17, :a "lucy", :b "ethel", :c 42, :e 6}
  • 91.
    Agents • Manage independentstate • State changes through actions, which are ordinary functions (state=>new-state) • Actions are dispatched using send or send-off, which return immediately • Actions occur asynchronously on thread-pool threads • Only one action per agent happens at a time
  • 92.
    Agents • Agent statealways accessible, via deref/@, but may not reflect all actions • Can coordinate with actions using await • Any dispatches made during an action are held until after the state of the agent has changed • Agents coordinate with transactions - any dispatches made during a transaction are held until it commits • Agents are not Actors (Erlang/Scala)
  • 93.
    Agents in Action (deffoo (agent {:a "fred" :b "ethel" :c 42 :d 17 :e 6})) @foo -> {:d 17, :a "fred", :b "ethel", :c 42, :e 6} (send foo assoc :a "lucy") @foo -> {:d 17, :a "fred", :b "ethel", :c 42, :e 6} (await foo) @foo -> {:d 17, :a "lucy", :b "ethel", :c 42, :e 6}
  • 94.
    MacrosClojure When to use • •Supplied with Clojure, and defined by user • Argument forms are passed as data to the Always! Or at least, anything that requires sequence handling: • Data streams macro• function, map (pmap) and reduce a new data Native parallel which returns • Database a replacement for the macro call structure ashandling • QL for transactional access to SQL through JDBC • (or • x Machine learning y) • clojure.hadoop, incanter (R-like statistical package library) (let [or__158 x] • becomes: HTTP, JSON parsing • XML, (if or__158 or__158 y)) • clojure.data.xml, clojure.data.json • •Many things that are ‘built-in’ to other languages • Logic programming! are just macros indevelopment with a strong focus on performance core.logic: project under Clojure (~75% faster than Prolog)
  • 95.
    Macros Further info • •Supplied with Clojure, and defined by user • Argument forms are passed as data to the Main sites: • Site of the language – http://clojure.org • macro#clojure IRC channel at freenode.net returns a new data function, which Planet Clojure – http://planet.clojure.in • the structure projecta(http://github.com/relevance/labrepl) – learning environment call • The labrepl as replacement for the macro • Try-Clojure (http://www.try-clojure.org/) – you can execute Clojure code via Web-browser • • x y) (or http://clojuredocs.org/ – documentation and examples • Books: • Programming Clojure – 2009th,[or__158 x] (let Clojure v. 1.0 • becomes: The Definitive Guide – 2010th, Clojure, v. 1.2 • Practical Clojure. (if or__158 or__158 y)) • • The Joy of Clojure Many things that are ‘built-in’ to other languages • Clojure in Action • just macros Wikibooks are Clojure Notes on RubyLearningClojure Clojure Programming on in •
  • 96.
    Thanks for yourattention!