JavaOne 2013 - Clojure for Java Developers

1,340 views
1,251 views

Published on

The fact that Clojure is a dialect of Lisp makes it feel completely alien to Java developers, and they miss the opportunity to learn this dynamic and functional programming language for the JVM. Clojure’s focus on immutability makes it very useful for concurrency. This presentation introduces Clojure in a way that feels natural to Java developers. By seeing how well Clojure interoperates with Java, you will learn how to take advantage of this wonderful language and still use all the frameworks and features of the JVM.

Published in: Technology, Education
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,340
On SlideShare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
29
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

JavaOne 2013 - Clojure for Java Developers

  1. 1. for Java developers Clojure jan.kronquist@jayway.com onsdag 25 september 13
  2. 2. About me onsdag 25 september 13
  3. 3. About me 1986 - Basic onsdag 25 september 13
  4. 4. About me 1990 - 68K assembly 1986 - Basic onsdag 25 september 13
  5. 5. About me 1990 - 68K assembly1986 - Basic 1995 - OOP onsdag 25 september 13
  6. 6. 1997 - University About me 1990 - 68K assembly1986 - Basic 1995 - OOP onsdag 25 september 13
  7. 7. 1997 - University About me 1990 - 68K assembly1986 - Basic 2005 - IoC,Aspects, Mixins 1995 - OOP onsdag 25 september 13
  8. 8. 2008 - Functional 1997 - University About me 1990 - 68K assembly1986 - Basic 2005 - IoC,Aspects, Mixins 1995 - OOP onsdag 25 september 13
  9. 9. 2012 - Lisp & dynamic typing 2008 - Functional 1997 - University About me 1990 - 68K assembly1986 - Basic 2005 - IoC,Aspects, Mixins 1995 - OOP onsdag 25 september 13
  10. 10. This talk is not A comprehensive introduction to Clojure About idiomatic Clojure Another talk about functional programming onsdag 25 september 13
  11. 11. Killer apps onsdag 25 september 13
  12. 12. Killer apps Prismatic onsdag 25 september 13
  13. 13. Killer apps Prismatic onsdag 25 september 13
  14. 14. Killer apps Prismatic Datomic Storm ClojureScript onsdag 25 september 13
  15. 15. What is Clojure? Created 2007 by Rich Hickey Lisp Runs on JVM, CLR & JavaScript Design for concurrency onsdag 25 september 13
  16. 16. Clojure example (defn divisible? [n d] (== 0 (mod n d))) (defn divides [n] (partial divisible? n)) (declare primes) (defn prime? [n] (not (some (divides n) (take-while #(< % n) primes)))) (def primes (lazy-cat [2 3 5] (filter prime? (drop 7 (range))))) onsdag 25 september 13
  17. 17. Why Clojure? onsdag 25 september 13
  18. 18. Why Clojure? Lisp - Code as data & Syntactic abstraction onsdag 25 september 13
  19. 19. Why Clojure? Lisp - Code as data & Syntactic abstraction Functional - Declarative, Immutable onsdag 25 september 13
  20. 20. Why Clojure? Lisp - Code as data & Syntactic abstraction Functional - Declarative, Immutable Interactive development environment onsdag 25 september 13
  21. 21. Why Clojure? Lisp - Code as data & Syntactic abstraction Functional - Declarative, Immutable Interactive development environment Great eco-system - dynamic helps compatibility onsdag 25 september 13
  22. 22. Why Clojure? Lisp - Code as data & Syntactic abstraction Functional - Declarative, Immutable Interactive development environment Great eco-system - dynamic helps compatibility Wrapper-free Java access onsdag 25 september 13
  23. 23. Why Clojure? Lisp - Code as data & Syntactic abstraction Functional - Declarative, Immutable Interactive development environment Great eco-system - dynamic helps compatibility Wrapper-free Java access Less complexity onsdag 25 september 13
  24. 24. Common complaints onsdag 25 september 13
  25. 25. Common complaints Lisp looks weird onsdag 25 september 13
  26. 26. Common complaints Dynamic typing is scary Lisp looks weird onsdag 25 september 13
  27. 27. Common complaints Dynamic typing is scary Lisp looks weird Just a toy language onsdag 25 september 13
  28. 28. Common complaints Dynamic typing is scary Lisp looks weird Macros? Are you crazy? Just a toy language onsdag 25 september 13
  29. 29. Lispness onsdag 25 september 13
  30. 30. Clojure Atomic Data Types Arbitrary precision integers: 12345678987654 Doubles: 1.234 BigDecimals: 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" Rich Hickey - Clojure for Java Programmers - http://www.youtube.com/watch?v=P76Vbsk_3J0 onsdag 25 september 13
  31. 31. JavaScript Data Structures Arrays [1, 2, 3] ["fred", "ethel", "lucy"] Objects {name: "Jan Kronquist", age: 37} onsdag 25 september 13
  32. 32. Clojure Data Structures Vectors [1, 2, 3] ["fred", "ethel", "lucy"] Maps {:name "Jan Kronquist", :age 37} move colon onsdag 25 september 13
  33. 33. Clojure Data Structures Vectors [1 2 3] ["fred" "ethel" "lucy"] Maps {:name "Jan Kronquist" :age 37} commas are whitespace! onsdag 25 september 13
  34. 34. Clojure Data Structures Vectors - indexed access [1 2 3] ["fred" "ethel" "lucy"] Maps {:name "Jan Kronquist" :age 37} Lists - singly linked (1 2 3 4 5) (fred ethel lucy) (list 1 2 3) Sets #{fred ethel lucy} onsdag 25 september 13
  35. 35. Demo in REPL user=> "hello" "hello" user=> 5 5 user=> [1 2 3] [1 2 3] user=> qwe java.lang.RuntimeException: Unable to resolve symbol: qwe user=> (def qwe "hello world") #'user/qwe user=> qwe "hello world" onsdag 25 september 13
  36. 36. "Hello world") The strangeness of Lisp println( onsdag 25 september 13
  37. 37. "Hello world") The strangeness of Lisp println( onsdag 25 september 13
  38. 38. "Hello world") The strangeness of Lisp println( (operator operand1 operand2 ...) Determines how the list is evaluated onsdag 25 september 13
  39. 39. (= (.toString (+ 1 2)) "3") Example evaluation (= (.toString (+ 1 2)) "3") onsdag 25 september 13
  40. 40. (= (.toString (+ 1 2)) "3") Example evaluation onsdag 25 september 13
  41. 41. (= (.toString (+ 1 2)) "3") Example evaluation (= (.toString 3) "3") onsdag 25 september 13
  42. 42. (= (.toString (+ 1 2)) "3") Example evaluation (= (.toString 3) "3") (= "3" "3") onsdag 25 september 13
  43. 43. (= (.toString (+ 1 2)) "3") Example evaluation (= (.toString 3) "3") (= "3" "3") true onsdag 25 september 13
  44. 44. onsdag 25 september 13
  45. 45. int i = 5; (def i 5) OR (let [i 5] ...) if (x > 5) { return y; } else { return z; } (if (> x 5) y z) x * y * z (* x y z) foo(x, y, z) (foo x y z) object.method(x, y) (.method object x y) public String sayHello(String x) { return "Hello " + x; } (defn sayHello [x] (str "Hello " x)) onsdag 25 september 13
  46. 46. int i = 5; (def i 5) OR (let [i 5] ...) if (x > 5) { return y; } else { return z; } (if (> x 5) y z) x * y * z (* x y z) foo(x, y, z) (foo x y z) object.method(x, y) (.method object x y) public String sayHello(String x) { return "Hello " + x; } (defn sayHello [x] (str "Hello " x)) onsdag 25 september 13
  47. 47. int i = 5; (def i 5) OR (let [i 5] ...) if (x > 5) { return y; } else { return z; } (if (> x 5) y z) x * y * z (* x y z) foo(x, y, z) (foo x y z) object.method(x, y) (.method object x y) public String sayHello(String x) { return "Hello " + x; } (defn sayHello [x] (str "Hello " x)) onsdag 25 september 13
  48. 48. int i = 5; (def i 5) OR (let [i 5] ...) if (x > 5) { return y; } else { return z; } (if (> x 5) y z) x * y * z (* x y z) foo(x, y, z) (foo x y z) object.method(x, y) (.method object x y) public String sayHello(String x) { return "Hello " + x; } (defn sayHello [x] (str "Hello " x)) onsdag 25 september 13
  49. 49. int i = 5; (def i 5) OR (let [i 5] ...) if (x > 5) { return y; } else { return z; } (if (> x 5) y z) x * y * z (* x y z) foo(x, y, z) (foo x y z) object.method(x, y) (.method object x y) public String sayHello(String x) { return "Hello " + x; } (defn sayHello [x] (str "Hello " x)) onsdag 25 september 13
  50. 50. int i = 5; (def i 5) OR (let [i 5] ...) if (x > 5) { return y; } else { return z; } (if (> x 5) y z) x * y * z (* x y z) foo(x, y, z) (foo x y z) object.method(x, y) (.method object x y) public String sayHello(String x) { return "Hello " + x; } (defn sayHello [x] (str "Hello " x)) onsdag 25 september 13
  51. 51. Java Quiz public static void main(String[] args) { int bang = 1; do while (bang>=1) System.out.print(" bang is "+ bang); while (bang>1); } onsdag 25 september 13
  52. 52. Macros onsdag 25 september 13
  53. 53. Working with Java classes (defn display [text] (let [frame (new JFrame "MyFrame")] (.add frame (new JLabel text)) (.setSize frame 300 200) (.setVisible frame true))) static void display(String text) { JFrame frame = new JFrame("MyFrame"); frame.add(new JLabel(text)); frame.setSize(300, 200); frame.setVisible(true); } onsdag 25 september 13
  54. 54. Working with Java classes (defn display [text] (let [frame (new JFrame "MyFrame")] (.add frame (new JLabel text)) (.setSize frame 300 200) (.setVisible frame true))) static void display(String text) { JFrame frame = new JFrame("MyFrame"); frame.add(new JLabel(text)); frame.setSize(300, 200); frame.setVisible(true); } (display "Hello World") onsdag 25 september 13
  55. 55. Working with Java classes (defn display [text] (let [frame (new JFrame "MyFrame")] (.add frame (new JLabel text)) (.setSize frame 300 200) (.setVisible frame true))) static void display(String text) { JFrame frame = new JFrame("MyFrame"); frame.add(new JLabel(text)); frame.setSize(300, 200); frame.setVisible(true); } a pattern! onsdag 25 september 13
  56. 56. static void display(String text) { JFrame frame = new JFrame("MyFrame"); with (frame) { .add(new JLabel(text)); .setSize(300, 200); .setVisible(true); } } Working with Java classes (defn display [text] (let [frame (new JFrame "MyFrame")] (.add frame (new JLabel text)) (.setSize frame 300 200) (.setVisible frame true))) onsdag 25 september 13
  57. 57. (defn display [text] (let [frame (new JFrame "MyFrame")] (doto frame (.add (new JLabel text)) (.setSize 300 200) (.setVisible true)))) Working with Java classes static void display(String text) { JFrame frame = new JFrame("MyFrame"); with (frame) { .add(new JLabel(text)); .setSize(300, 200); .setVisible(true); } } onsdag 25 september 13
  58. 58. (defn display [text] (doto (new JFrame "MyFrame") (.add (new JLabel text)) (.setSize 300 200) (.setVisible true))) Working with Java classes static void display(String text) { JFrame frame = new JFrame("MyFrame"); frame.add(new JLabel(text)); frame.setSize(300, 200); frame.setVisible(true); } onsdag 25 september 13
  59. 59. (defn display [text] (doto (new JFrame "MyFrame") (.add (new JLabel text)) (.setSize 300 200) (.setVisible true))) Working with Java classes static void display(String text) { JFrame frame = new JFrame("MyFrame"); frame.add(new JLabel(text)); frame.setSize(300, 200); frame.setVisible(true); } Ok, nice, but in practice you would never want something like this? onsdag 25 september 13
  60. 60. static void write(String fileName, String text) throws IOException { try (Writer writer = new FileWriter(fileName)) { writer.write(text); } } Trust me, you want macros onsdag 25 september 13
  61. 61. static void write(String fileName, String text) throws IOException { try (Writer writer = new FileWriter(fileName)) { writer.write(text); } } Trust me, you want macros (defn write [fileName text] (with-open [writer (new FileWriter fileName)] (.write writer text))) onsdag 25 september 13
  62. 62. Toy? onsdag 25 september 13
  63. 63. Structure in Modules - package Abstraction - interface Implementation - class onsdag 25 september 13
  64. 64. Structure in Modules - package Abstraction - interface Implementation - class Problems mutable state? static methods? inheritance? constants? onsdag 25 september 13
  65. 65. Structure in Modules namespace - first-class, dynamic, import, aliasing Abstraction defprotocol - can be added later Implementation defrecord - immutable, equals, hashcode, etc deftype - may mutate, only user functionilty reify - singleton gen-class & proxy - for Java interop onsdag 25 september 13
  66. 66. Records - creating (ns my.namespace) (defrecord Person [firstName lastName]) (new Person "Jan" "Kronquist") onsdag 25 september 13
  67. 67. Records - creating ; #my.namespace.Person{:firstName "Jan", :lastName "Kronquist"} (ns my.namespace) (defrecord Person [firstName lastName]) (new Person "Jan" "Kronquist") onsdag 25 september 13
  68. 68. Records - field access ; #my.namespace.Person{:firstName "Jan", :lastName "Kronquist"} (ns my.namespace) (defrecord Person [firstName lastName]) (new Person "Jan" "Kronquist") (def person (new Person "Jan" "Kronquist")) (.firstName person) onsdag 25 september 13
  69. 69. Records - field access ; #my.namespace.Person{:firstName "Jan", :lastName "Kronquist"} (ns my.namespace) (defrecord Person [firstName lastName]) (new Person "Jan" "Kronquist") (def person (new Person "Jan" "Kronquist")) (.firstName person) ; "Jan" onsdag 25 september 13
  70. 70. Records - named parameters ; #my.namespace.Person{:firstName "Jan", :lastName "Kronquist"} (ns my.namespace) (defrecord Person [firstName lastName]) (new Person "Jan" "Kronquist") (def person (new Person "Jan" "Kronquist")) (.firstName person) ; "Jan" (map->Person {:lastName "Kronquist" :firstName "Jan"}) onsdag 25 september 13
  71. 71. Records - named parameters ; #my.namespace.Person{:firstName "Jan", :lastName "Kronquist"} (ns my.namespace) (defrecord Person [firstName lastName]) (new Person "Jan" "Kronquist") (def person (new Person "Jan" "Kronquist")) (.firstName person) ; "Jan" (map->Person {:lastName "Kronquist" :firstName "Jan"}) ; #my.namespace.Person{:firstName "Jan", :lastName "Kronquist"} onsdag 25 september 13
  72. 72. Records and protocols (defprotocol Nameable (getName [this])) onsdag 25 september 13
  73. 73. Records and protocols (defprotocol Nameable (getName [this])) (defrecord Person [firstName lastName] Nameable (getName [this] (str firstName " " lastName))) (getName (new Person "Jan" "Kronquist")) ; "Jan Kronquist" Person class implements Nameable interface onsdag 25 september 13
  74. 74. Records and protocols (defprotocol Nameable (getName [this])) (defrecord Person [firstName lastName]) (extend-protocol Nameable Person (getName [this] (str (.firstName this) " " (.lastName this)))) (getName (new Person "Jan" "Kronquist")) ; "Jan Kronquist" (defrecord Person [firstName lastName] Nameable (getName [this] (str firstName " " lastName))) (getName (new Person "Jan" "Kronquist")) ; "Jan Kronquist" Person class implements Nameable interface Person extended by Nameable after definition! onsdag 25 september 13
  75. 75. Records and protocols (defprotocol Nameable (getName [this])) (defrecord Person [firstName lastName]) (extend-protocol Nameable Person (getName [this] (str (.firstName this) " " (.lastName this)))) (getName (new Person "Jan" "Kronquist")) ; "Jan Kronquist" (defrecord Person [firstName lastName] Nameable (getName [this] (str firstName " " lastName))) (.getName (new Person "Jan" "Kronquist")) ; "Jan Kronquist" Method getName exists on Person class onsdag 25 september 13
  76. 76. Records and protocols (defprotocol Nameable (getName [this])) (defrecord Person [firstName lastName]) (extend-protocol Nameable Person (getName [this] (str (.firstName this) " " (.lastName this)))) (.getName (new Person "Jan" "Kronquist")) ; IllegalArgumentException No matching field found: getName (defrecord Person [firstName lastName] Nameable (getName [this] (str firstName " " lastName))) (.getName (new Person "Jan" "Kronquist")) ; "Jan Kronquist" Method getName exists on Person class But not in this case! onsdag 25 september 13
  77. 77. Editors and IDEs? Eclipse - Counterclockwise IntelliJ - La Clojure Light Table Sublime Textmate Emacs onsdag 25 september 13
  78. 78. Eclipse Counterclockwise ✓Restrictive formatting ✓Paren coloring ✓Typing suggestions ✓Being Eclipse https://code.google.com/p/counterclockwise/ onsdag 25 september 13
  79. 79. Light table ✓Cool ✓Insta-REPL http://www.lighttable.com/ onsdag 25 september 13
  80. 80. Sublime ✓General purpose editor ✓Typing suggestions http://www.sublimetext.com/ onsdag 25 september 13
  81. 81. Repositories Maven style Maven central http://clojars.org/repo onsdag 25 september 13
  82. 82. Build tools Maven plugin Gradle plugin Leiningen onsdag 25 september 13
  83. 83. Leiningen (defproject myproject "0.5.0-SNAPSHOT" :description "A project for doing things." :url "http://github.com/foo/bar" :dependencies [[org.clojure/clojure "1.5.1"] [ring/ring-core "1.2.0 "]] :plugins [[lein-ring "0.4.5"]]) onsdag 25 september 13
  84. 84. Dynamic typing onsdag 25 september 13
  85. 85. Dynamic typing? Robert Smallshire - The Unreasonable Effectiveness of Dynamic Typing for Practical Programs onsdag 25 september 13
  86. 86. Dynamic typing is scary Compiler won’t find errors Limited tool support Performance? onsdag 25 september 13
  87. 87. What made me think twice Web server onsdag 25 september 13
  88. 88. What made me think twice Web server onsdag 25 september 13
  89. 89. Clojure makes dynamic typing ok REPL Immutable data structure Pure functions Automated tests onsdag 25 september 13
  90. 90. Dynamic typing and performance? Clojure is compiled to bytecode Generally good enough! onsdag 25 september 13
  91. 91. Dynamic typing and performance? Clojure is compiled to bytecode Generally good enough! (defn len [^String x] (.length x)) onsdag 25 september 13
  92. 92. Studies Stefan Hanenberg & Lutz Prechelt Dynamic is more productive No difference in reliability Robert Smallshire - 2 % defects are type errors (GitHub) onsdag 25 september 13
  93. 93. Conclusion onsdag 25 september 13
  94. 94. Macros? Are you crazy? Dynamic typing is scary Convinced? Lisp looks weird Just a toy language onsdag 25 september 13
  95. 95. Macros? Are you crazy? Dynamic typing is usable Convinced? Lisp looks weird Just a toy language REPL Immutable data structure Pure functions Automated tests onsdag 25 september 13
  96. 96. Macros? Are you crazy? Lisp is consistent Dynamic typing is usable Convinced? Just a toy language REPL Immutable data structure Pure functions Automated tests (operation operand1 operand2 ...) onsdag 25 september 13
  97. 97. Macros? Are you crazy? Lisp is consistent Dynamic typing is usable Convinced? REPL Immutable data structure Pure functions Automated tests Interesting language (operation operand1 operand2 ...) Namespaces Prototcols Records onsdag 25 september 13
  98. 98. Macros? Are you crazy? Lisp is consistent Dynamic typing is usable Convinced? REPL Immutable data structure Pure functions Automated tests Interesting language (operation operand1 operand2 ...) Lazy seqs STM Functional Namespaces Prototcols Records onsdag 25 september 13
  99. 99. Macros? Maybe....... Lisp is consistent Dynamic typing is usable Convinced? REPL Immutable data structure Pure functions Automated tests Interesting language (operation operand1 operand2 ...) Lazy seqs STM Functional Namespaces Prototcols Records try (Writer writer = new FileWriter(fileName)) writer.write(text); } onsdag 25 september 13
  100. 100. Macros? Maybe....... Lisp is consistent Dynamic typing is usable Convinced? REPL Immutable data structure Pure functions Automated tests Interesting language (operation operand1 operand2 ...) Lazy seqs STM Functional Namespaces Prototcols Records try (Writer writer = new FileWriter(fileName)) writer.write(text); } DSL Reuse Structure onsdag 25 september 13
  101. 101. Further resources http://clojure.org/ http://tryclj.com/ http://www.4clojure.com http://clojure-doc.org/ onsdag 25 september 13
  102. 102. Questions? onsdag 25 september 13

×