• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Clojure: a LISP for the JVM
 

Clojure: a LISP for the JVM

on

  • 1,477 views

 

Statistics

Views

Total Views
1,477
Views on SlideShare
1,477
Embed Views
0

Actions

Likes
1
Downloads
20
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n

Clojure: a LISP for the JVM Clojure: a LISP for the JVM Presentation Transcript

  • 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” dont 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” dont 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” dont 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 userpublic abstract class Shape { abstract public double getArea(); • Argument forms are passed as data to the ...} macro function, which returns a new datapublic class Rectangle extends Shape { // its 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 userpublic 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 datapublic class Rectangle extends Shape { // its 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 userpublic 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 datapublic class Rectangle extends Shape { // its 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 userpublic 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 datapublic class Rectangle extends Shape { // its 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 userpublic 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 datapublic class Rectangle extends Shape { // its 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 doesnt pass this test, it shouldnt 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 doesnt 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.” • “Its 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 evaluationCodeText characters Effect Compiler bytecode Executable JVM .class/.jar Run java
  • Syntactic AbstractionCodeText characters Effect Reader data structures characters evaluator/ bytecode JVM compiler data structuresYou 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 HashMapHashMap int count 16int count 15 INode rootINode 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 - Directreferences 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!