Clojure for Java developers - Stockholm

1,351 views

Published on

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

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

No notes for slide

Clojure for Java developers - Stockholm

  1. 1. Clojure for Java developers jan.kronquist@jayway.com
  2. 2. About me 2012 2008 -& dynamic typing - Lisp Functional 1997 68K assembly 1986 OOP 2005 1995 --Aspects, Mixins 1990IoC,University - - - Basic
  3. 3. This talk is not A comprehensive introduction to Clojure! About idiomatic Clojure! Another talk about functional programming
  4. 4. Killer apps Prismatic! Datomic! Storm! ClojureScript
  5. 5. What is Clojure? Created 2007 by Rich Hickey! Lisp! Runs on JVM, CLR & JavaScript! Design for concurrency
  6. 6. 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)))))
  7. 7. Why Clojure? Lisp - Code as data & Syntactic abstraction! Functional - Declarative, Immutable! Interactive development environment! Great eco-system! Wrapper-free Java access
  8. 8. Common complaints Dynamic typing is scary Lisp looks weird Just a toy language Macros? Are you crazy?
  9. 9. Lispness
  10. 10. 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
  11. 11. JavaScript Data Structures Arrays! [1, 2, 3] ["fred", "ethel", "lucy"] Objects! {name: "Jan Kronquist", age: 37}
  12. 12. Clojure Data Structures Vectors! [1, 2, 3] ["fred", "ethel", "lucy"] Maps! {:name "Jan Kronquist", :age 37} move colon
  13. 13. Clojure Data Structures Vectors! [1 2 3] ["fred" "ethel" "lucy"] Maps! {:name "Jan Kronquist" :age 37} commas are whitespace!
  14. 14. 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}
  15. 15. 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"
  16. 16. The strangeness of Lisp println("Hello world") (operator operand1 operand2 ...) Determines how the list is evaluated
  17. 17. Example evaluation (= (.toString (+ 1 2)) "3") (= (.toString 3) "3") (= "3" "3") true
  18. 18. 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))
  19. 19. Java Quiz public static void main(String[] args) { int bang = 1; do while (bang>=1) System.out.print(" bang is "+ bang); while (bang>1); }
  20. 20. Macros
  21. 21. 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); } (defn display [text] (let [frame (new JFrame "MyFrame")] (.add frame (new JLabel text)) (.setSize frame 300 200) (.setVisible frame true))) a pattern! (display "Hello World")
  22. 22. 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); } } (defn display [text] (let [frame (new JFrame "MyFrame")] (.add frame (new JLabel text)) (.setSize frame 300 200) (.setVisible frame true)))
  23. 23. 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); } } (defn display [text] (let [frame (new JFrame "MyFrame")] (doto frame (.add (new JLabel text)) (.setSize 300 200) (.setVisible true))))
  24. 24. 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); } (defn display [text] (doto (new JFrame "MyFrame") (.add (new JLabel text)) (.setSize 300 200) (.setVisible true))) Ok, nice, but in practice you would never want something like this?
  25. 25. Trust me, you want macros static void write(String fileName, String text) throws IOException { try (Writer writer = new FileWriter(fileName)) { writer.write(text); } } (defn write [fileName text] (with-open [writer (new FileWriter fileName)] (.write writer text)))
  26. 26. Toy?
  27. 27. Structure in Modules - package! Abstraction - interface! Implementation - class! ! Problems! mutable state?! static methods?! inheritance?! constants?
  28. 28. 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
  29. 29. Records - creating (ns my.namespace) (defrecord Person [firstName lastName]) (new Person "Jan" "Kronquist") ; #my.namespace.Person{:firstName "Jan", :lastName "Kronquist"}
  30. 30. Records - field access (ns my.namespace) (defrecord Person [firstName lastName]) (new Person "Jan" "Kronquist") ; #my.namespace.Person{:firstName "Jan", :lastName "Kronquist"} (def person (new Person "Jan" "Kronquist")) (.firstName person) ; "Jan"
  31. 31. Records - named parameters (ns my.namespace) (defrecord Person [firstName lastName]) (new Person "Jan" "Kronquist") ; #my.namespace.Person{:firstName "Jan", :lastName "Kronquist"} (def person (new Person "Jan" "Kronquist")) (.firstName person) ; "Jan" (map->Person {:lastName "Kronquist" :firstName "Jan"}) ; #my.namespace.Person{:firstName "Jan", :lastName "Kronquist"}
  32. 32. Records and protocols (defprotocol Nameable (getName [this])) Person class implements Nameable interface (defrecord Person [firstName lastName] Nameable (getName [this] (str firstName " " lastName))) ! (getName (new Person "Jan" "Kronquist")) ! ; "Jan Kronquist" Person Nameable extended by after definition! (defrecord Person [firstName lastName]) ! (extend-protocol Nameable Person (getName [this] (str (.firstName this) " " (.lastName this)))) ! (getName (new Person "Jan" "Kronquist")) ! ; "Jan Kronquist"
  33. 33. Records and protocols (defprotocol Nameable (getName [this])) (defrecord Person [firstName lastName] Nameable (getName [this] (str firstName " " lastName))) Method getName exists on Person class ! (.getName (new Person "Jan" "Kronquist")) ! ; "Jan Kronquist" (defrecord Person [firstName lastName]) ! (extend-protocol Nameable Person (getName [this] (str (.firstName this) " " (.lastName this)))) ! (getName (new Person "Jan" "Kronquist")) ! ; "Jan Kronquist"
  34. 34. Records and protocols (defprotocol Nameable (getName [this])) (defrecord Person [firstName lastName] Nameable (getName [this] (str firstName " " lastName))) Method getName exists on Person class ! (.getName (new Person "Jan" "Kronquist")) ! ; "Jan Kronquist" (defrecord Person [firstName lastName]) ! But not in this case! (extend-protocol Nameable Person (getName [this] (str (.firstName this) " " (.lastName this)))) ! (.getName (new Person "Jan" "Kronquist")) ! ; IllegalArgumentException No matching field found: getName
  35. 35. Editors and IDEs? Eclipse - Counterclockwise! IntelliJ - La Clojure! Light Table! Sublime! Textmate! Emacs
  36. 36. Eclipse Counterclockwise https://code.google.com/p/counterclockwise/ ✓Restrictive formatting! ✓Typing suggestions! ✓Paren coloring! ✓Being Eclipse
  37. 37. Light table http://www.lighttable.com/ ✓Cool! ✓Insta-REPL
  38. 38. Sublime http://www.sublimetext.com/ ✓General purpose editor! ✓Typing suggestions
  39. 39. Repositories Maven style! Maven central! http://clojars.org/repo
  40. 40. Build tools Maven plugin! Gradle plugin! Leiningen
  41. 41. 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"]])
  42. 42. Dynamic typing
  43. 43. Dynamic typing? Robert Smallshire - The Unreasonable Effectiveness of Dynamic Typing for Practical Programs
  44. 44. Dynamic typing is scary Compiler won’t find errors! Limited tool support! Performance?
  45. 45. What made me think twice Web server
  46. 46. Clojure makes dynamic typing ok REPL! Immutable data structure ! Pure functions! Automated tests
  47. 47. Studies Stefan Hanenberg & Lutz Prechelt! Dynamic is more productive! No difference in reliability! Robert Smallshire - 2 % defects are type errors (GitHub)
  48. 48. Still not convinced? Clojure is compiled to bytecode! Type hints! (defn len [^String x] (.length x)) ! core.typed (t/ann f [Integer -> Integer]) (defn f [x] (int (inc x)))
  49. 49. Conclusion
  50. 50. Convinced? REPL! Immutable data structure ! Pure functions! Automated tests Dynamic typing is scary usable (operation operand1 operand2 ...) Lisp looks weird is consistent Namespaces! Prototcols! Records Interesting language Just a toy Lazy seqs! STM! Functional try (Writer writer = new FileWriter(fileName)) { writer.write(text); } Macros? Are you crazy? Maybe....... DSL! Reuse! Structure
  51. 51. Further resources http://clojure.org/! http://tryclj.com/! http://www.4clojure.com! http://clojure-doc.org/
  52. 52. Questions?

×