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.
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. 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. 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. 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. 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. 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. 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
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. 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. 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. 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. (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. (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. (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. 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
63. Structure in
Modules - package
Abstraction - interface
Implementation - class
onsdag 25 september 13
64. Structure in
Modules - package
Abstraction - interface
Implementation - class
Problems
mutable state?
static methods?
inheritance?
constants?
onsdag 25 september 13
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. Records - creating
(ns my.namespace)
(defrecord Person [firstName lastName])
(new Person "Jan" "Kronquist")
onsdag 25 september 13
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. 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. 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. 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. 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
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. 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. 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. 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. Editors and IDEs?
Eclipse - Counterclockwise
IntelliJ - La Clojure
Light Table
Sublime
Textmate
Emacs
onsdag 25 september 13
86. Dynamic typing is scary
Compiler won’t find errors
Limited tool support
Performance?
onsdag 25 september 13
87. What made me think twice
Web server
onsdag 25 september 13
88. What made me think twice
Web server
onsdag 25 september 13
89. Clojure makes dynamic typing ok
REPL
Immutable data structure
Pure functions
Automated tests
onsdag 25 september 13
90. Dynamic typing and performance?
Clojure is compiled to bytecode
Generally good enough!
onsdag 25 september 13
91. Dynamic typing and performance?
Clojure is compiled to bytecode
Generally good enough!
(defn len [^String x]
(.length x))
onsdag 25 september 13
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
94. Macros? Are you crazy?
Dynamic typing is scary
Convinced?
Lisp looks weird
Just a toy language
onsdag 25 september 13
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. 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. 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. 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. 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. 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