Upcoming SlideShare
×

# Clojure: a LISP for the JVM

1,956 views

Published on

Published in: Technology
3 Likes
Statistics
Notes
• Full Name
Comment goes here.

Are you sure you want to Yes No
• Be the first to comment

Views
Total views
1,956
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
47
0
Likes
3
Embeds 0
No embeds

No notes for slide
• \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

1. 1. Macros• Supplied with Clojure, and deﬁned 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
2. 2. Macros• Supplied with Clojure, and deﬁned 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. 3. Macros Java dominance• Supplied with Clojure, and deﬁned 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
4. 4. Macros But!• Supplied with Clojure, and deﬁned 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 veriﬁability... 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
5. 5. Macros Nouns The Kingdom of• Supplied with Clojure, and deﬁned by user• Argument forms are passed as data to the macro function, which returns a new data • Nouns (classes, objects) are ﬁrst-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
6. 6. Macros Nouns The Kingdom of• Supplied with Clojure, and deﬁned 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
7. 7. Macros Nouns The Kingdom of• Supplied with Clojure, and deﬁned 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
8. 8. Macros Nouns The Kingdom of• Supplied with Clojure, and deﬁned 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
9. 9. Liskov substitution Macros principle (LSP) user• Supplied with Clojure, and deﬁned 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 veriﬁability? are just macros inhave modularity? can we say we Clojure •
10. 10. Macros A simple (?) example• Supplied with Clojure, and deﬁned 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
11. 11. Macros A simple (?) example • Supplied with Clojure, and deﬁned 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; }}
12. 12. Macros A simple (?) example • Supplied with Clojure, and deﬁned 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; }}
13. 13. Macros A simple (?) example • Supplied with Clojure, and deﬁned 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; } } }}
14. 14. Macros A simple (?) example • Supplied with Clojure, and deﬁned 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; }}
15. 15. Macros A simple (?) example • Supplied with Clojure, and deﬁned 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; } } }}
16. 16. Macros LSP! Java ignores• Supplied with Clojure, and deﬁned 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 deﬁne a mathematical or ontological relation but are just macros in Clojure rather behavioral
17. 17. Macrosveriﬁable Java code is not• Supplied with Clojure, and deﬁned 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 veriﬁable (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
18. 18. Macrosmatter? Does it really• Supplied with Clojure, and deﬁned 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
19. 19. Macrosmatter? Does it really• Supplied with Clojure, and deﬁned by user• • People tend toare passed as data toand Argument forms say that veriﬁability 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
20. 20. Macrosmatter? Does it really• Supplied with Clojure, and deﬁned by user• • People tend toare passed as data toand Argument forms say that veriﬁability 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
21. 21. Macrosmatter? Does it really• Supplied with Clojure, and deﬁned by user• • People tend toare passed as data toand Argument forms say that veriﬁability 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
22. 22. Macrosmatter? Does it really• Supplied with Clojure, and deﬁned by user• • People tend toare passed as data toand Argument forms say that veriﬁability 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 ﬁxing the other languages late units: rely are just macros in Clojure
23. 23. Macrosmatter? Does it really• Supplied with Clojure, and deﬁned 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
24. 24. Macrosmatter? Does it really• Supplied with Clojure, and deﬁned 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
25. 25. Macrosmatter? Does it really• Supplied with Clojure, and deﬁned 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
26. 26. Macrosmatter? Does it really• Supplied with Clojure, and deﬁned 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
27. 27. Macrosmatter? Does it really• Supplied with Clojure, and deﬁned 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
28. 28. Macrosmatter? Does it really• Supplied with Clojure, and deﬁned 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
29. 29. Macrosmatter? Does it really• Supplied with Clojure, and deﬁned 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
30. 30. Macros state The problem of• Supplied with Clojure, and deﬁned 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
31. 31. Macros state The problem of• Supplied with Clojure, and deﬁned 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
32. 32. Macros State and concurrency• Supplied with Clojure, and deﬁned 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
33. 33. Macros State and concurrency• Supplied with Clojure, and deﬁned 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
34. 34. Macros State and concurrency• Supplied with Clojure, and deﬁned 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
35. 35. Macros State and concurrency• Supplied with Clojure, and deﬁned 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
36. 36. Macros State and concurrency• Supplied with Clojure, and deﬁned 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
37. 37. Macros State and concurrency• Supplied with Clojure, and deﬁned 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
38. 38. Macros State and concurrency• Supplied with Clojure, and deﬁned 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
39. 39. Macros State and concurrency• Supplied with Clojure, and deﬁned 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
40. 40. Macros State and concurrency• Supplied with Clojure, and deﬁned 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
41. 41. Macros State and concurrency• Supplied with Clojure, and deﬁned 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
42. 42. Macros Easy != Simple• Supplied with Clojure, and deﬁned 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-veriﬁability, languages syntax add are ‘built-in’ are just macros in Clojure [1] http://www.norvig.com/design-patterns/ppframe.htm
43. 43. Macros• Supplied with Clojure, and deﬁned 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
44. 44. Macros• Supplied with Clojure, and deﬁned 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
45. 45. Macros• Supplied with Clojure, and deﬁned 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
46. 46. Macros Functional Programming• Supplied with Clojure, and deﬁned by user •• Argument forms are passed as data to the Computation as the composition and evaluation of functions • Functions as ﬁrst-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 • Inﬁnite (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
47. 47. Macros LISP• Supplied with Clojure, and deﬁned 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
48. 48. Macros• Supplied with Clojure, and deﬁned 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
49. 49. Macros • Supplied with Clojure, and deﬁned 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
50. 50. Macros of LISP Contributions• Supplied with Clojure, and deﬁned 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
51. 51. Macros code? Is this data or• Supplied with Clojure, and deﬁned 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>
52. 52. A moment of genius: Macros (eval)deﬁned 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 ﬁrst 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
53. 53. Macros Language matters• Supplied with Clojure, and deﬁned 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.ﬂownet.com/gat/papers/lisp-java.pdf
54. 54. Macros• Supplied with Clojure, and deﬁned 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
55. 55. Macros There is a pattern• •Supplied with Clojure, and deﬁned 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
56. 56. Macros Why Clojure?• Supplied with Clojure, and deﬁned 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
57. 57. Dynamic development• REPL - Read-eval-print-loop• Deﬁne functions on the ﬂy• Load and compile code at runtime• Introspection• Interactive environment
58. 58. Traditional evaluationCodeText characters Effect Compiler bytecode Executable JVM .class/.jar Run java
59. 59. Syntactic AbstractionCodeText characters Effect Reader data structures characters evaluator/ bytecode JVM compiler data structuresYou Program data structures Program (macro)
60. 60. 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”
61. 61. 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
62. 62. 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
63. 63. Expressions• Everything is an expression• All data literals represent themselves • Except: • Symbols • looks for binding to value, locally, then globally • Lists • An operation form
64. 64. Operation forms• (op ...)• op can be either: • one of very few special ops • macro • expression which yields a function
65. 65. 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
66. 66. 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
67. 67. Macros• Supplied with Clojure, and deﬁned 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
68. 68. Macros Macros• Supplied with Clojure, and deﬁned 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 # sufﬁx 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
69. 69. 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)
70. 70. Sequences• Abstraction of traditional Lisp lists• (seq coll) • if collection is non-empty, return seq object on it, else nil• (first seq) • returns the ﬁrst element• (rest seq) • returns a seq of the rest of the elements, or nil if no more
71. 71. Macros Lazy Evaluation• Supplied with Clojure, and deﬁned by user • A lazy sequence is aare passed unfolded unless strictly• Argument forms necessary sequence not as data to the macro function, an inﬁnitereturns 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)• • Beneﬁts (let [or__158 x] becomes: (if or__158 or__158 y)) • Avoidance of unnecessary calculations• Many thingsand usage of inﬁnite structures • Creation that are ‘built-in’ to other languages are just macros inbe forced if needed Clojure • Early evaluation can
72. 72. 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
73. 73. Polymorphism: Macros multimethodsby user• Supplied with Clojure, and deﬁned • 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- speciﬁed dispatch functions• (or On y) or more several parameters • x one (let [or__158 dispatch−fn) + set of x]• becomes: (if or__158 • Deﬁned as (defmulti func−name or__158 y)) implementations (via defmethod)• • You things that are ‘built-in’ relationships with Many can also deﬁne hierarchical to other languages are just macros them in dispatch derive, and use in Clojure
74. 74. 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)
75. 75. 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.
76. 76. 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)
77. 77. 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)
78. 78. Path Copying HashMapHashMap int count 16int count 15 INode rootINode root
79. 79. Concurrency• Interleaved/simultaneous execution• Must avoid seeing/yielding inconsistent data• The more components there are to the data, the more difﬁcult to keep consistent• The more steps in a logical change, the more difﬁcult to keep consistent• Opportunities for automatic parallelism • Emphasis here on coordination
80. 80. 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 difﬁcult • Languages matter!
81. 81. Typical OO - Directreferences to Mutable Objects foo :a ? :b ? :c 42 :d ? :e 6 • Uniﬁes identity and value • Anything can change at any time • Consistency is a user problem
82. 82. 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
83. 83. Macros Parallel execution• Supplied with Clojure, and deﬁned 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
84. 84. 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
85. 85. Structural Sharing• Key to efﬁcient ‘copies’ and therefore persistence• Everything is ﬁnal so no chance of interference• Thread safe• Iteration safe
86. 86. 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
87. 87. 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
88. 88. 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 conﬂict • Must avoid side-effects!
89. 89. 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}
90. 90. 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
91. 91. Agents• Agent state always accessible, via deref/@, but may not reﬂect 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)
92. 92. 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}
93. 93. MacrosClojure When to use• •Supplied with Clojure, and deﬁned 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)
94. 94. Macros Further info• •Supplied with Clojure, and deﬁned 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 Deﬁnitive 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 •
95. 95. Thanks for your attention!