Slide 1

Slide 1 text

Wir lösen das – persönlich! Clojure Functional Programming meets the JVM Stefan Tilkov | @stilkov | innoQ Sunday, October 28, 12

Slide 2

Slide 2 text

© 2012 innoQ Deutschland GmbH Sunday, October 28, 12

Slide 3

Slide 3 text

Wir lösen das – persönlich! There’s more to life than OOP Functional Programming meets the JVM Stefan Tilkov | @stilkov | innoQ Sunday, October 28, 12

Slide 4

Slide 4 text

© 2011 innoQ Deutschland GmbH Stefan Tilkov [email protected] http://www.innoq.com/blog/st/ @stilkov Sunday, October 28, 12

Slide 5

Slide 5 text

© 2011 innoQ Deutschland GmbH http://rest-http.info Sunday, October 28, 12

Slide 6

Slide 6 text

© 2011 innoQ Deutschland GmbH SoftwareArchitekTOUR Michael Stal - Christian Weyer - Markus Völter - Stefan Tilkov http://heise.de/developer/podcast Sunday, October 28, 12

Slide 7

Slide 7 text

© 2011 innoQ Deutschland GmbH http://www.innoq.com Sunday, October 28, 12

Slide 8

Slide 8 text

© 2011 innoQ Deutschland GmbH http://upload.wikimedia.org/wikip Sunday, October 28, 12

Slide 9

Slide 9 text

© 2011 innoQ Deutschland GmbH Clojure http://upload.wikimedia.org/wikipedia/en/1/1a/Clo A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system Concurrent programming support Bi-directional Java interop Immutable persistent data structures Sunday, October 28, 12

Slide 10

Slide 10 text

© 2011 innoQ Deutschland GmbH Lisp?? Sunday, October 28, 12

Slide 11

Slide 11 text

© 2011 innoQ Deutschland GmbH Lots of irritating silly parentheses? Sunday, October 28, 12

Slide 12

Slide 12 text

© 2011 innoQ Deutschland GmbH Sunday, October 28, 12

Slide 13

Slide 13 text

© 2011 innoQ Deutschland GmbH Sunday, October 28, 12

Slide 14

Slide 14 text

© 2011 innoQ Deutschland GmbH http://xkcd.com/297/ Sunday, October 28, 12

Slide 15

Slide 15 text

© 2011 innoQ Deutschland GmbH http://www.flickr.com/photos/nicolasrolland/3063007013/ Sunday, October 28, 12

Slide 16

Slide 16 text

© 2011 innoQ Deutschland GmbH http://www.tbray.org/ongoing/When/200x/2008/09/25/-big/R0010774.jpg.html Rich Hickey Sunday, October 28, 12

Slide 17

Slide 17 text

© 2011 innoQ Deutschland GmbH Intro Sunday, October 28, 12

Slide 18

Slide 18 text

© 2011 innoQ Deutschland GmbH Clojure Environment Clojuresque (Gradle) Leiningen Sunday, October 28, 12

Slide 19

Slide 19 text

© 2011 innoQ Deutschland GmbH Data structures Numbers 2 3 4 0.234 3/5 -2398989892820093093090292321 Strings "Hello" "World" Characters \a \b \c Keywords :first :last Symbols a b c Regexps #"Ch.*se" Lists (a b c) ((:first :last "Str" 3) (a b)) Vectors [2 4 6 9 23] [2 4 6 [8 9] [10 11] 9 23] Maps {:de "Deutschland", :fr "France"} Sets #{"Bread" "Cheese" "Wine"} Sunday, October 28, 12

Slide 20

Slide 20 text

© 2011 innoQ Deutschland GmbH Syntax Sunday, October 28, 12

Slide 21

Slide 21 text

© 2011 innoQ Deutschland GmbH “You’ve just seen it” – Rich Hickey Sunday, October 28, 12

Slide 22

Slide 22 text

© 2011 innoQ Deutschland GmbH Syntax (def my-set #{:a :b :c :c :c}) ;; #{:a :b :c} (def v [2 4 6 9 23]) (v 0) ;; 2 (v 2) ;; 6 (def people {:pg "Phillip", :st "Stefan"}) (people :st) ;; "Stefan" (:pg people) ;; "Phillip" (:xyz people) ;; nil (+ 2 2) ;; 4 (+ 2 3 5 4) ;; 14 (class (/ 4 3)) ;; clojure.lang.Ratio (* (/ 4 3) 3) ;; 4 (format "Hello, %s # %d" "world" 1) Sunday, October 28, 12

Slide 23

Slide 23 text

© 2011 innoQ Deutschland GmbH Syntax ; (a 2 3) (quote (a 2 3)) ;; (a 2 3) '(a 2 3) ;; (a 2 3) ; Evaluation (eval '(format "Hello, %s" "World")) (eval (read-string "(+ 2 2)")) (format "Hello, %s # %d" "world" 1) ; "Hello, World # 1" (apply format ["Hello, %s # %d" "world" 1]) Sunday, October 28, 12

Slide 24

Slide 24 text

© 2011 innoQ Deutschland GmbH Functions (fn [x] (format "The value is %s\n" x)) ;; user$eval__1706$fn__1707@390b755d ((fn [x] (format "The value is %s\n" x)) "Hello") ;; "The value is Hello" (def testfn (fn [x] (format "The value is %s\n" x))) (testfn "Hello") (defn testfn [x] (format "The value is %s\n" x)) (testfn "Hello") Sunday, October 28, 12

Slide 25

Slide 25 text

© 2011 innoQ Deutschland GmbH Functions (defn even [x] (= 0 (rem x 2))) (even 4) ;; true (def even-alias even) (even-alias 2) ;; true (defn every-even? [l] (every? even l)) (every-even? '(2 4 6 8 9)) ;; false (every? #(= 0 (rem % 2)) '(2 4 6 8 9)) ;; false Sunday, October 28, 12

Slide 26

Slide 26 text

© 2011 innoQ Deutschland GmbH Closures (defn make-counter [initial-value] (let [current-value (atom initial-value)] (fn [] (swap! current-value inc)))) (def counter1 (make-counter 0)) (counter1) ;; 1 (counter1) ;; 2 (def counter2 (make-counter 17)) (counter1) ;; 3 (counter2) ;; 18 (counter1) ;; 4 (counter2) ;; 19 Sunday, October 28, 12

Slide 27

Slide 27 text

© 2011 innoQ Deutschland GmbH Recursion (defn reduce-1 [f val coll] (if (empty? coll) val (reduce-1 f (f val (first coll)) (rest coll)))) (reduce-1 + 0 [1 2 3 4]) ;; 10 (reduce-1 + 0 (range 5)) ;; 10 (reduce-1 + 0 (range 50)) ;; 1225 (reduce-1 + 0 (range 50000)) ;; java.lang.StackOverflowError Sunday, October 28, 12

Slide 28

Slide 28 text

© 2011 innoQ Deutschland GmbH (defn reduce-2 [f val coll] (if (empty? coll) val (recur f (f val (first coll)) (rest coll)))) (defn reduce-1 [f val coll] (if (empty? coll) val (reduce-1 f (f val (first coll)) (rest coll)))) Recursion (reduce-2 + 0 [1 2 3 4]) ;; 10 (reduce-2 + 0 (range 5)) ;; 10 (reduce-2 + 0 (range 50)) ;; 1225 (reduce-2 + 0 (range 50000)) ;; 1249975000 Sunday, October 28, 12

Slide 29

Slide 29 text

© 2011 innoQ Deutschland GmbH Example (ns sample.grep "A simple complete Clojure program." (:use [clojure.contrib.io :only [read-lines]]) (:gen-class)) (defn numbered-lines [lines] (map vector (iterate inc 0) lines)) (defn grep-in-file [pattern file] {file (filter #(re-find pattern (second %)) (numbered-lines (read-lines file)))}) (defn grep-in-files [pattern files] (apply merge (map #(grep-in-file pattern %) files))) (defn print-matches [matches] (doseq [[fname submatches] matches, [line-no, match] submatches] (println (str fname ":" line-no ":" match)))) (defn -main [pattern & files] (if (or (nil? pattern) (empty? files)) (println "Usage: grep ") (do (println (format "grep started with pattern %s and file(s) %s" pattern (apply str (interpose ", " files)))) (print-matches (grep-in-files (re-pattern pattern) files)) (println "Done.")))) Sunday, October 28, 12

Slide 30

Slide 30 text

© 2011 innoQ Deutschland GmbH Macros (log "Hello, World") Tue Apr 27 19:06:43 CEST 2010: Hello, World (def *debug* true) (defn log [msg] (if *debug* (printf "%s: %s\n" (java.util.Date.) msg))) (log (format "Hello, World %d" (* 9 9)))) Tue Apr 27 19:06:45 CEST 2010: Hello, World 81 Sunday, October 28, 12

Slide 31

Slide 31 text

© 2011 innoQ Deutschland GmbH Macros (defmacro log [body] `(if *debug* (printf "%s: %s\n" (java.util.Date.) ~body))) (log "Hello, World") Tue Apr 27 19:06:43 CEST 2010: Hello, World (macroexpand '(log "Hello, World")) (def *debug* true) (if user/*debug* (printf "%s: %s\n" (java.util.Date.) "Hello, World")) (macroexpand '(log (format "Hello, World %d" (* 9 9)))) (if *debug* (printf "%s: %s\n" (java.util.Date.) (format "Hello, World %d" (* 9 9)))) Sunday, October 28, 12

Slide 32

Slide 32 text

© 2011 innoQ Deutschland GmbH Macros (defmacro with-debug [body] `(binding [*debug* true] ~body)) Tue Apr 27 19:22:35 CEST 2010: Hello, World Tue Apr 27 19:22:35 CEST 2010: Clojure rocks (with-debug (log "Hello, World") (log "Clojure rocks")) (binding [*debug* false] (log "Hello, World")) Sunday, October 28, 12

Slide 33

Slide 33 text

© 2011 innoQ Deutschland GmbH Macros (defmacro with-debug [body] `(binding [*debug* true] ~body)) (macroexpand '(binding [*debug* true] (log "Hello, World"))) (let* [] (clojure.core/push-thread-bindings (clojure.core/hash-map (var *debug*) true)) (try (log "Hello, World") (finally (clojure.core/pop-thread-bindings)))) Sunday, October 28, 12

Slide 34

Slide 34 text

© 2011 innoQ Deutschland GmbH Lots of other cool stu ‣ Persistent data structures ‣ Sequences ‣ Support for concurrent programming ‣ Destructuring ‣ List comprehensions ‣ Metadata ‣ Optiional type information ‣ Multimethods ‣ Pre & Post Conditions ‣ Records/Protocols ‣ Extensive core and contrib libraries ‣ … Sunday, October 28, 12

Slide 35

Slide 35 text

© 2011 innoQ Deutschland GmbH State Sunday, October 28, 12

Slide 36

Slide 36 text

© 2011 innoQ Deutschland GmbH 4711: Person first: John last: Smith 0815: Person first: Jane last: Doe The Problem! Sunday, October 28, 12

Slide 37

Slide 37 text

© 2011 innoQ Deutschland GmbH Immutability user> (def v (vec (range 10))) user> (assoc v 1 99) [0 1 2 3 4 5 6 7 8 9] user> v #'user/v [0 99 2 3 4 5 6 7 8 9] [0 1 2 3 4 5 6 7 8 9] user> v user> (def v2 (assoc v 1 99)) user> v2 #'user/v2 [0 99 2 3 4 5 6 7 8 9] Sunday, October 28, 12

Slide 38

Slide 38 text

© 2011 innoQ Deutschland GmbH user> (def v (vec (range 10))) user> (def v2 (assoc v 1 99)) 9 4 7 0 1 6 8 3 5 2 v 99 v2 Sunday, October 28, 12

Slide 39

Slide 39 text

© 2011 innoQ Deutschland GmbH Persistent Data Structures ‣ Pure functional programming model ‣ E cient implementation ‣ Structural sharing ‣ Thread-safe ‣ Iteration-safe ‣ Based on Bit-partioned hash tries ‣ “Transient” data structures if needed ‣ Sunday, October 28, 12

Slide 40

Slide 40 text

© 2011 innoQ Deutschland GmbH Performance Guarantees hash-map sorted-map hash-set sorted-set vector queue list lazy seq conj near- constant logarithmic near- constant logarithmic constant (tail) constant (tail) constant (head) constant (head) assoc near- constant logarithmic - - near- constant - - - dissoc near- constant logarithmic - - - - - - disj - - near- constant logarithmic - - - - nth - - - - near- constant linear linear linear get near- constant logarithmic near- constant logarithmic near- constant - - - pop - - - - constant (tail) constant (head) constant (head) constant (head) peek - - - - constant (tail) constant (head) constant (head) constant (head) count constant constant constant constant constant constant constant linear Sunday, October 28, 12

Slide 41

Slide 41 text

© 2011 innoQ Deutschland GmbH Sequences Standard API for everything sequencable Collections Strings Native Java arrays java.lang.Iterable Anything that supports rst, rest, cons Sunday, October 28, 12

Slide 42

Slide 42 text

© 2011 innoQ Deutschland GmbH Sequences Standard API for everything sequencable “Lazy” sequences (def n (iterate (fn [x] (+ x 1)) 0)) (def fives (map #(* 5 %) n)) (take 10 fives) Sunday, October 28, 12

Slide 43

Slide 43 text

© 2011 innoQ Deutschland GmbH Sequences Standard API for everything sequencable “Lazy” sequences Extensive library apply butlast concat cons cycle distinct doall dorun doseq drop drop-last drop-while empty? every? rst le-seq lter rst fnext for interleave interpose into into-array iterate iterator-seq keys last lazy-cat lazy-seq line-seq map mapcat next n rst nnext not-any? not-empty not-every? nth nthnext partition pmap range re-seq reduce remove repeat repeatedly replace replicate rest resultset- seq reverse rseq rsubseq second seq seq? seque set some sort sort-by split-at split-with subseq take take-nth take-while to-array-2d tree-seq vals vec when- rst xml-seq zipmap … Sunday, October 28, 12

Slide 44

Slide 44 text

© 2012 innoQ Deutschland GmbH Syntax Idioms Sunday, October 28, 12

Slide 45

Slide 45 text

© 2012 innoQ Deutschland GmbH OOP Thinking model domains with classes & interfaces encapsulate data in objects prefer speci c over generic solutions explicitly provide for generic access Sunday, October 28, 12

Slide 46

Slide 46 text

© 2012 innoQ Deutschland GmbH Data Sunday, October 28, 12

Slide 47

Slide 47 text

© 2012 innoQ Deutschland GmbH Data structures vs. objects public class Point { private final double x; private final double y; public Point(double x, double y) { this.x = x; this.y = y; } } Point p1 = new Point(3, 4); (def p1 [3 4]) Sunday, October 28, 12

Slide 48

Slide 48 text

© 2012 innoQ Deutschland GmbH Data structures vs. objects (def p1 [3 4]) Immutable Reusable Compatible Sunday, October 28, 12

Slide 49

Slide 49 text

© 2012 innoQ Deutschland GmbH Data structures vs. objects import static java.lang.Math.sqrt; public class Point { private final double x; private final double y; public Point(double x, double y) { this.x = x; this.y = y; } public double distanceTo(Point other) { double c1 = other.x - this.x; double c2 = other.y - this.y; return sqrt(c1 * c1 + c2 * c2); } } Sunday, October 28, 12

Slide 50

Slide 50 text

© 2012 innoQ Deutschland GmbH Data structures vs. objects (import-static java.lang.Math sqrt) (defn distance [[x1 y1] [x2 y2]] (let [c1 (- x2 x1) c2 (- y2 y1)] (sqrt (+ (* c1 c1) (* c2 c2))))) Sunday, October 28, 12

Slide 51

Slide 51 text

© 2012 innoQ Deutschland GmbH Data structures vs. objects (defn rand-seq [limit] (repeatedly #(rand-int limit))) (take 10 (partition 2 (rand-seq 10))) in nite randoms pairs of random ints 10 random points ;((3 6) (6 1) (8 5) (0 7) (3 8) (0 6) (1 6) (7 6) (0 1) (8 9)) Sunday, October 28, 12

Slide 52

Slide 52 text

© 2012 innoQ Deutschland GmbH Data structures vs. objects (defn circumference [vertices] (reduce + (map distance vertices (drop 1 (cycle vertices))))) in nite repetition seq without rst all ;((3 6) (6 1) (8 5) (0 7) (3 8) (0 6) (1 6) (7 6) (0 1) (8 9)) ;((6 1) (8 5) (0 7) (3 8) (0 6) (1 6) (7 6) (0 1) (8 9) (3 6)) ;58.06411369758525 ... Sunday, October 28, 12

Slide 53

Slide 53 text

© 2012 innoQ Deutschland GmbH assoc assoc-in butlast concat conj cons count cycle difference dissoc distinct distinct? drop-last empty empty? every? filter first flatten group-by interleave interpose intersection into join lazy-cat mapcat merge merge-with not-any? not-empty? not-every? nth partition partition-all partition-by peek pop popy project remove replace rest rseq select select-keys shuffle some split-at split-with subvec take take-last take-nth take-while union update-in Sunday, October 28, 12

Slide 54

Slide 54 text

© 2012 innoQ Deutschland GmbH Maps (def projects #{{:id "1", :kind :time-material, :description "Consulting for BigCo", :budget 25000, :team [:joe, :chuck, :james]} {:id "2", :kind :fixed-price, :description "Development for Startup", :budget 100000, :team [:john, :chuck, :james, :bill]} {:id "3", :kind :fixed-price, :description "Clojure Training", :budget 3000, :team [:joe, :john]}}) Sunday, October 28, 12

Slide 55

Slide 55 text

© 2012 innoQ Deutschland GmbH Map access (defn all-members [projects] (reduce conj #{} (flatten (map :team projects)))) seq of vectors seq of members with duplicates set of all team members ;#{:chuck :joe :james :john :bill} (all-members projects) Sunday, October 28, 12

Slide 56

Slide 56 text

© 2012 innoQ Deutschland GmbH Map access & coupling (defn all-members [projects] (reduce conj #{} (flatten (map :team projects)))) #{{:id "2", :kind :fixed-price, :description "Development for Startup", :budget 100000, :team [:john, :chuck, :james, :bill]}} Sunday, October 28, 12

Slide 57

Slide 57 text

© 2012 innoQ Deutschland GmbH Map access & coupling (defn all-members [projects] (reduce conj #{} (flatten (map :team projects)))) #{{:id "2", :kind :fixed-price, :description "Development for Startup", :budget 100000, :team [:john, :chuck, :james, :bill]}} :team :team Sunday, October 28, 12

Slide 58

Slide 58 text

© 2012 innoQ Deutschland GmbH [{:kind "fixed-price", :team ["john" "chuck" "james" "bill"], :budget 100000, :id "2", :description "Development for Startup"} {:kind "fixed-price", :team ["joe" "john"], :budget 3000, :id "3", :description "Clojure Training"} {:kind "time-material", :team ["joe" "chuck" "james"], :budget 25000, :id "1", :description "Consulting for BigCo"}] [{"kind":"fixed-price", "team":["john", "chuck", "james", "bill"], "budget":100000, "id":"2", "description":"Development for Startup"}, {"kind":"fixed-price", "team":["joe", "john"], "budget":3000, "id":"3", "description":"Clojure Training"}, {"kind":"time-material", "team":["joe", "chuck", "james"], "budget":25000, "id":"1", "description":"Consulting for BigCo"}] (json-str) (read-json) Sunday, October 28, 12

Slide 59

Slide 59 text

© 2012 innoQ Deutschland GmbH (defn ...) (defmacro ...) (defmulti ...) (defmethod ...) (defn- ...) (def ^:private ...) (ns com.example.some-ns "Well-documented ns" (:use [com.example.n1 :only [xyz]]) (:require [com.example.ns2 :as n2])) Sunday, October 28, 12

Slide 60

Slide 60 text

© 2012 innoQ Deutschland GmbH Implementation Interface Functions w/ simple data Sunday, October 28, 12

Slide 61

Slide 61 text

© 2011 innoQ Deutschland GmbH Concurrency Support Sunday, October 28, 12

Slide 62

Slide 62 text

© 2011 innoQ Deutschland GmbH Core Ideas ‣ Everything immutable ‣ Shared state for reading ‣ No changes to shared state ‣ Isolated threads ‣ Re-use of platform facilities ‣ Java Integration (java.util.concurrent.Callable) Sunday, October 28, 12

Slide 63

Slide 63 text

© 2011 innoQ Deutschland GmbH def & binding (binding [some-var some-var] (println some-var) ;; 10 (set! some-var 30) (println some-var)) ;; 30 (binding [some-var 30] (println some-var)) ;; 30 (def some-var 10) (def some-var 10) (println some-var) ;; 10 Sunday, October 28, 12

Slide 64

Slide 64 text

© 2011 innoQ Deutschland GmbH Atoms (def a (atom "Initial Value")) (println @a) ;; "Initial Value" (swap! a #(apply str (reverse %))) (println @a) ;; "eulaV laitinI" (swap! a #(apply str (reverse %))) (println @a) ;; "Initial Value" Sunday, October 28, 12

Slide 65

Slide 65 text

© 2011 innoQ Deutschland GmbH Atoms (defn run-thread-fn [f] (.start (new Thread f))) (defn add-list-item [coll-atom x] (swap! coll-atom #(conj % x))) (def int-list (atom ())) ;; () (let [run-fn (fn [x] (run-thread-fn #(add-list-item int-list x)))] (doall (map run-fn (range 100)))) ;; (98 97 96 ... 0) (def int-list (atom ())) ;; () (run-thread-fn #(add-list-item int-list 5)) ;; (5) (run-thread-fn #(add-list-item int-list 3)) ;; (3 5) (run-thread-fn #(add-list-item int-list 1)) ;; (1 3 5) Sunday, October 28, 12

Slide 66

Slide 66 text

© 2011 innoQ Deutschland GmbH Refs (defn make-account [balance owner] {:balance balance, :owner owner}) (defn withdraw [account amount] (assoc account :balance (- (account :balance) amount))) (defn deposit [account amount] (assoc account :balance (+ (account :balance) amount))) Sunday, October 28, 12

Slide 67

Slide 67 text

© 2011 innoQ Deutschland GmbH Refs (defn init-accounts [] (def acc1 (ref (make-account 1000 "alice"))) (def acc2 (ref (make-account 1000 "bob"))) (def acc3 (ref (make-account 1000 "charles")))) (defn transfer [from to amount] (dosync (alter from withdraw amount) (alter to deposit amount))) Sunday, October 28, 12

Slide 68

Slide 68 text

© 2011 innoQ Deutschland GmbH Refs (init-accounts) (do (run-thread-fn #(transfer acc1 acc2 100)) (transfer acc3 acc1 400)) acc1: {:balance 1000, :owner "alice"} acc2: {:balance 1000, :owner "bob"} acc3: {:balance 1000, :owner "charles"} acc1: {:balance 1300, :owner "alice"} acc2: {:balance 1100, :owner "bob"} acc3: {:balance 600, :owner "charles"} Sunday, October 28, 12

Slide 69

Slide 69 text

© 2011 innoQ Deutschland GmbH Refs (defn slow-transfer [from to amount] (dosync (sleep 1000) (alter from withdraw amount) (alter to deposit amount))) (do (run-thread-fn #(slow-transfer acc1 acc2 100)) (transfer acc3 acc1 400)) acc1: {:balance 1600, :owner "alice"} acc2: {:balance 1200, :owner "bob"} acc3: {:balance 200, :owner "charles"} acc1: {:balance 1300, :owner "alice"} acc2: {:balance 1100, :owner "bob"} acc3: {:balance 600, :owner "charles"} Sunday, October 28, 12

Slide 70

Slide 70 text

© 2011 innoQ Deutschland GmbH So ware Transactional Memory (STM) ‣ Multi-version concurrency control (MVCC) ‣ Atomic changes to multiple refs ‣ Non-blocking, retry-based ‣ “Read committed” ‣ Can't help with non-pure functions ‣ Works with atoms and agents ref-set alter commute ensure deref/@ throw Sunday, October 28, 12

Slide 71

Slide 71 text

© 2011 innoQ Deutschland GmbH So ware Transactional Memory ref-set alter commute ensure deref/@ Reads value of reference, blocks none Reads value of reference, blocks writers Reads value of reference, blocks none, delayed write, last writer wins Changes reference to new value, blocks writers Atomically reads, computes, sets reference value, blocks writers throw Rolls back transaction Sunday, October 28, 12

Slide 72

Slide 72 text

© 2011 innoQ Deutschland GmbH Agents Asynchronous execution Run on java.util.concurrent thread pool await await-for send-off send agent (let [my-agent (agent 0) slow-fn (fn [x] (sleep 1000) (inc x))] (send my-agent slow-fn) (println @my-agent) (sleep 2000) (println @my-agent)) ;; 0 ;; 1 deref/@ Sunday, October 28, 12

Slide 73

Slide 73 text

© 2011 innoQ Deutschland GmbH Agents await await-for send-off send agent deref/@ Creates agent with initial value Dispatch function to agent for execution Dispatch long-running function Read agent value Wait for agent to execute function(s) dispatched from current thread Same as await, but with timeout Sunday, October 28, 12

Slide 74

Slide 74 text

© 2011 innoQ Deutschland GmbH Validators (def some-var 10) (set-validator! #'some-var #(< % 100)) (def some-var 101) ;; Invalid reference state ;; [Thrown class java.lang.IllegalStateException] (def some-var) (defn limit-validator [limit] (fn [new-value] (if (< new-value limit) true (throw (Exception. (format "Value %d is larger than limit %d" new-value limit)))))) (set-validator! #'some-var (limit-validator 100)) (def some-var 101) ;; Value 101 is larger than limit 100 ;; [Thrown class java.lang.Exception] Sunday, October 28, 12

Slide 75

Slide 75 text

© 2011 innoQ Deutschland GmbH Watchers (def *a* (atom 0)) (def *events* (atom ())) (defn log-event [coll s] (swap! coll conj s)) (log-event *events* "some event") ;; ("some event") (log-event *events* "yet another event") ;; ("yet another event" "some event") (defn log-value-change [key ref old new] (if (= key :log) (log-event *events* (format "value of %s changed from %d to %d" ref old new)))) (log-value-change :log 'x 0 1) ;; ("value of x changed from 0 to 1" "yet another event" "some event") (add-watch a :log log-value-change) (swap! a inc) ;; 1 (deref *events*) ;; ("value of clojure.lang.Atom@59829c6b changed from 0 to 1" ;; "value of x changed from 0 to 1" "yet another event" "some event") Sunday, October 28, 12

Slide 76

Slide 76 text

© 2011 innoQ Deutschland GmbH Futures & Promises user> (doc future) ------------------------- clojure.core/future ([& body]) Macro Takes a body of expressions and yields a future object that will invoke the body in another thread, and will cache the result and return it on all subsequent calls to deref/@. If the computation has not yet finished, calls to deref/@ will block. user> (doc promise) ------------------------- clojure.core/promise ([]) Alpha - subject to change. Returns a promise object that can be read with deref/@, and set, once only, with deliver. Calls to deref/@ prior to delivery will block. All subsequent derefs will return the same delivered value without blocking. Sunday, October 28, 12

Slide 77

Slide 77 text

© 2011 innoQ Deutschland GmbH thread-local global shared def binding set! single multiple sync async atom dosync ref agent Sunday, October 28, 12

Slide 78

Slide 78 text

© 2011 innoQ Deutschland GmbH Summary ‣ Built on immutablity from the ground up ‣ Powerful collections ‣ Extensive sequence library ‣ Built-in concurrency primitives Sunday, October 28, 12

Slide 79

Slide 79 text

© 2011 innoQ Deutschland GmbH Java Integration Sunday, October 28, 12

Slide 80

Slide 80 text

© 2011 innoQ Deutschland GmbH Clojure → Java (new java.lang.String "Hello") (java.lang.String. "Even quicker") (java.io.File/separator) (import '(java.io InputStream File)) (File/separator) (. System/out println "Hello") (.println System/out "Hello") (every? #(instance? java.util.Collection %) '([1 2] '(1 2) #{1 2})) ;; true (defn blank? [s] (every? #(Character/isWhitespace %) s)) (blank? "some string") ;; false (blank? "") ;; true Sunday, October 28, 12

Slide 81

Slide 81 text

© 2011 innoQ Deutschland GmbH Clojure 㲗 Java (Collections/sort java-collection (make-comparator #(. %1 compareTo %2))) ;; # (defn make-comparator [compare-fn] (proxy [java.util.Comparator] [] (compare [left right] (compare-fn left right)))) (import '(java.util Vector Collections)) (def java-collection (Vector.)) (doto java-collection (.add "Gamma") (.add "Beta") (.add "Alpha")) ;; # Sunday, October 28, 12

Slide 82

Slide 82 text

© 2011 innoQ Deutschland GmbH Clojure ← Java package com.innoq.test; public interface ClojureInterface { String reverse(String s); } package com.innoq.test; public class ClojureMain { public static void main(String[] args) { ClojureInterface cl = new ClojureClass(); System.out.println("String from Clojure: " + cl.reverse("Hello, World")); } } (ns com.innoq.test) (gen-class :name com.innoq.test.ClojureClass :implements [com.innoq.test.ClojureInterface] :prefix class-) (defn class-reverse [this s] (apply str (reverse s))) Sunday, October 28, 12

Slide 83

Slide 83 text

© 2011 innoQ Deutschland GmbH http://clojure.org/ http://peepcode.com/products/functional-programming-with-clojure http://vimeo.com/channels/fulldisclojure #clojure freenode [email protected] build.clojure.org http://en.wikibooks.org/wiki/Clojure http://technomancy.us/136 Books http://stuartsierra.com/ http://www.bestinclass.dk/index.php/blog/ http://technomancy.us/ http://kotka.de/blog/ http://blog.fogus.me/ Blogs Core Screencasts http://www.assembla.com/wiki/show/clojure/Getting_Started http://github.com/relevance/labrepl Sunday, October 28, 12

Slide 84

Slide 84 text

© 2011 innoQ Deutschland GmbH Auf deutsch ... “Auf die Finger geschaut”; Phillip Ghadir “Clojure unter der Lupe”; Burkhard Neppert “Clojure - in der Praxis?”; Stefan Tilkov (alle drei Javamagazin, 2.2011) “Clojure: Ein pragmatisches Lisp für die JVM” Stefan Tilkov, heise Developer Juli 2010 http://bit.ly/ceLkmT “Clojure: Funktional, parallel, genial” Burkhard Neppert, Stefan Tilkov dreiteilige Artikelserie in JavaSPEKTRUM 02-04/2010 http://bit.ly/caHJ8f “Clojure” Stefan Kamphause, Tim Oliver Kaiser dpunkt Verlag http://www.dpunkt.de/buecher/3372.html Sunday, October 28, 12

Slide 85

Slide 85 text

© 2011 innoQ Deutschland GmbH Q&A Stefan Tilkov [email protected] http://www.innoq.com/blog/st/ Twitter: stilkov http://xkcd.com/224/ Sunday, October 28, 12