Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp...

72
Clojure for OOP folks Stefan Tilkov | @stilkov | innoQ http://xkcd.com/297/ Friday, May 17, 13

Transcript of Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp...

Page 1: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

Clojure for OOP folks Stefan Tilkov | @stilkov | innoQ

http://xkcd.com/297/

Friday, May 17, 13

Page 2: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

OOP Thinkingmodel domains with classes & interfaces

encapsulate data in objects

prefer speci!c over generic solutions

explicitly provide for generic access

Friday, May 17, 13

Page 3: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

27.04.10 14:17http://upload.wikimedia.org/wikipedia/en/1/1a/Clojure-glyph.svg

Page 1 of 1

Friday, May 17, 13

Page 4: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2011 innoQ Deutschland GmbH

Clojure 27.04.10 14:17http://upload.wikimedia.org/wikipedia/en/1/1a/Clojure-glyph.svg

Page 1 of 1

A practical Lisp variant for the JVM Functional programming

Dynamic Typing Full-featured macro system

Concurrent programming supportBi-directional Java interop

Immutable persistent data structures

Friday, May 17, 13

Page 5: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbHhttp://www.tbray.org/ongoing/When/200x/2008/09/25/-big/R0010774.jpg.html

Rich Hickey

Friday, May 17, 13

Page 6: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2011 innoQ Deutschland GmbH

Data structuresNumbers 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"}

Friday, May 17, 13

Page 7: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2011 innoQ Deutschland GmbH

Syntax

Friday, May 17, 13

Page 8: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

“You’ve just seen it” – Rich Hickey

Friday, May 17, 13

Page 9: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 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)

Friday, May 17, 13

Page 10: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 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])

Friday, May 17, 13

Page 11: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 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")

Friday, May 17, 13

Page 12: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 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

Friday, May 17, 13

Page 13: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 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

Friday, May 17, 13

Page 14: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 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

Friday, May 17, 13

Page 15: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 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

Friday, May 17, 13

Page 16: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 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 <pattern> <file...>")    (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."))))

Friday, May 17, 13

Page 17: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 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

‣ …

Friday, May 17, 13

Page 18: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Syntax Idioms

Friday, May 17, 13

Page 19: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 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

Friday, May 17, 13

Page 20: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Namespaces

Friday, May 17, 13

Page 21: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

... just like Java packages

Friday, May 17, 13

Page 22: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

require: (re-)load libs:reload, :reload-all, :as

refer: import names:exclude [], :only [], :rename {…:…}

use: require + refer:exclude [], :only [], :rename {…:…}

ns: create namespace:require, :refer, :use, :gen-class

Handle var name clashesReduce dependencies

Dynamic reloadingNamespace aliases

Convenient REPL usage

Flexible handling in sourcesProvide encapsulation

Friday, May 17, 13

Page 23: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

require: (re-)load libs:reload, :reload-all, :as, :refer

refer: import names:exclude [], :only [], :rename {…:…}

ns: create namespace:require, :refer, :use, :gen-class

Handle var name clashesReduce dependencies

Dynamic reloadingNamespace aliasesConvenient REPL usage

Flexible handling in sourcesProvide encapsulation

Friday, May 17, 13

Page 24: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

(defn ...)(defmacro ...)(defmulti ...)(defmethod ...)

(defn- ...)(def ^:private ...)(def ^:dynamic ...)

(ns com.example.some-ns  "Well-documented ns"   (:use [com.example.n1 :only [xyz]])   (:require [com.example.ns2 :as n2]))

Friday, May 17, 13

Page 25: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Data

Friday, May 17, 13

Page 26: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Data structures vs. objectspublic 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])

Friday, May 17, 13

Page 27: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Data structures vs. objects(def p1 [3 4])

Immutable

Reusable

Compatible

Friday, May 17, 13

Page 28: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Data structures vs. objectsimport 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);    }}

Friday, May 17, 13

Page 29: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 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)))))

Friday, May 17, 13

Page 30: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 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))

Friday, May 17, 13

Page 31: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Data structures vs. objects(defn circumference   [vertices]  (reduce + (map distance vertices (drop 1 (cycle vertices)))))

in!nite repetition

seq without !rstall

;((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

...

Friday, May 17, 13

Page 32: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

assocassoc-inbutlastconcatconjconscountcycledifferencedissocdistinctdistinct?drop-lastemptyempty?every?filterfirstflatten

group-byinterleaveinterposeintersectionintojoinlazy-catmapcatmergemerge-withnot-any?not-empty?not-every?nthpartitionpartition-allpartition-bypeekpop

popyprojectremovereplacerestrseqselectselect-keysshufflesomesplit-atsplit-withsubvectaketake-lasttake-nthtake-whileunionupdate-in

Friday, May 17, 13

Page 33: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

app

request

response

objects object

Friday, May 17, 13

Page 34: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

public interface Servlet  {        void init(ServletConfig servletConfig)         throws ServletException;        ServletConfig getServletConfig();        void service(ServletRequest servletRequest,                  ServletResponse servletResponse)         throws ServletException, IOException;        String getServletInfo();        void destroy();}

Friday, May 17, 13

Page 35: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

public interface HttpServletRequest extends ServletRequest {       public String getAuthType();

    public Cookie[] getCookies();              

    public Enumeration<String> getHeaders(String name);

    public Enumeration<String> getHeaderNames();

    public String getMethod();

    public String getQueryString();

    public String getRemoteUser();

    public HttpSession getSession(boolean create);

    public boolean authenticate(HttpServletResponse response)         throws IOException,ServletException;        public void login(String username, String password)         throws ServletException;...

Friday, May 17, 13

Page 36: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

public interface HttpServletResponse extends ServletResponse {

    public void addCookie(Cookie cookie);

    public boolean containsHeader(String name);       public void sendError(int sc, String msg) throws IOException;

    public void sendRedirect(String location) throws IOException;

    public void setDateHeader(String name, long date);

    public void addDateHeader(String name, long date);

    public void setHeader(String name, String value);

    public void addHeader(String name, String value);

    public void setStatus(int sc);

    public int getStatus();...

Friday, May 17, 13

Page 37: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

app

request

response

data function

Friday, May 17, 13

Page 38: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

(defn hello-world-app [req]  {:status 200   :headers {"Content-Type" "text/plain"}   :body "Hello, World!"})

(hello-world-app {:uri "/foo"                  :request-method :get})> {...}

(run-jetty hello-world-app {:port 8080})

Friday, May 17, 13

Page 39: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 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]}})

Friday, May 17, 13

Page 40: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 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)

Friday, May 17, 13

Page 41: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 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]}}

Friday, May 17, 13

Page 42: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 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

Friday, May 17, 13

Page 43: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 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)

Friday, May 17, 13

Page 44: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 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]))

Friday, May 17, 13

Page 45: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Implementation

Interface

Functionsw/ simple data

Friday, May 17, 13

Page 46: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2011 innoQ Deutschland GmbH

Closures

Friday, May 17, 13

Page 47: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2011 innoQ Deutschland GmbH

(defn make-id  [prefix id]  (join "-" [prefix (Long/toString id 16)]))

(prj-id);; "prj-1"(prj-id);; "prj-2"(prj-id);; "prj-3"

(defn make-project [map]  (assoc map :id (prj-id)))

(defn id-generator  ([prefix]     (id-generator prefix 0))  ([prefix v]     (let [cnt (atom v)]       (fn [] (make-id prefix (swap! cnt inc))))))

(def prj-id (id-generator "prj"))

Friday, May 17, 13

Page 48: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Meet Miss Grant

http

://w

ww

.info

rmit.

com

/art

icle

s/ar

ticle

.asp

x?p=

1592

379

Friday, May 17, 13

Page 49: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

(def fsm  (make-fsm :idle :doorOpened            {:idle              [[unlock-door lock-panel]                                 {:doorClosed :active}]             :active            [[] {:drawerOpened :waitingForLight                                     :lightOn :waitingForDrawer}]             :waitingForLight   [[] {:lightOn :unlockedPanel}]             :waitingForDrawer  [[] {:drawerOpened :unlockedPanel}]             :unlockedPanel     [[unlock-panel lock-door]                                 {:panelClosed :idle}]}))

(defn unlock-door [] (println "Unlocking door"))(defn lock-door [] (println "Locking door"))(defn unlock-panel [] (println "Unlocking panel"))(defn lock-panel [] (println "Locking panel"))

Friday, May 17, 13

Page 50: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2011 innoQ Deutschland GmbH

(defn make-fsm  "creates an fsm with initial state s0, a reset event, and a map of transitions.  [state-transitions] must be a map of state->[[f1 f2 ...] {e0->s0, e1->s2, ...}]"  [s0 reset-event state-transitions ]  (let [s (atom s0)]    (fn [evt]      (if (= evt reset-event)        (do          (println  "Reset event, returning to " s0)          (swap! s (fn [_] s0)))        (let [[actions transitions] (state-transitions @s)]          (if-let [new-state (transitions evt)]            (do              (println  "Event" evt "causes transition from" @s "to" new-state)              (doseq [f actions] (f))              (swap! s (fn [_] new-state)))            (println "Unexpected/unhandled event" evt "in state" @s)))))))

Friday, May 17, 13

Page 51: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2011 innoQ Deutschland GmbH

(dorun (map fsm [:doorClosed :lightOn :drawOpened :panelClosed]))

(def fsm  (make-fsm :idle :doorOpened            {:idle              [[unlock-door lock-panel]                                 {:doorClosed :active}]             :active            [[] {:drawerOpened :waitingForLight                                     :lightOn :waitingForDrawer}]             :waitingForLight   [[] {:lightOn :unlockedPanel}]             :waitingForDrawer  [[] {:drawerOpened :unlockedPanel}]             :unlockedPanel     [[unlock-panel lock-door]                                 {:panelClosed :idle}]}))

;; Event :doorClosed causes transition from :idle to :active;; Unlocking door;; Locking panel;; Event :lightOn causes transition from :active to :waitingForDrawer;; Event :drawerOpened causes transition from :waitingForDrawer to :unlockedPanel;; Event :panelClosed causes transition from :unlockedPanel to :idle;; Unlocking panel;; Locking door;; Reset event, returning to  :idle

Friday, May 17, 13

Page 52: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Map Function

Multimethod

Friday, May 17, 13

Page 53: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Method problems“Global” state

Coarse-grained re-use

Simple-minded dispatch

Friday, May 17, 13

Page 54: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Methods vs. Multimethods

Methods Multimethods

Dispatch Type customizable

on # of args 1 arbitrary

Hierarchybased on type

inheritancecustomizable

Friday, May 17, 13

Page 55: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Multimethods(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]}})

Friday, May 17, 13

Page 56: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Multimethods(defmulti expected-revenue :kind)

(defmethod expected-revenue :default [p]  (:budget p))  (defmethod expected-revenue :fixed-price [p]  (* 0.8 (:budget p)))  (defn total-expected-revenue  [projects]  (reduce + (map expected-revenue projects)))

Friday, May 17, 13

Page 57: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Multimethods(defn make-rectangle  [[p1 p2 p3 p4 :as vertices]]  (let [a (distance p1 p2)        b (distance p2 p3)]    (assert (= a (distance p3 p4)))    (assert (= b (distance p4 p1)))    {:kind :rectangle, :vertices vertices, :a a, :b b}))

(defn make-circle  [center r]  {:kind :circle, :center center, :r r})

(defmulti area :kind)

(defmethod area :rectangle  [{:keys [a b]}]  (* a b))  (defmethod area :circle  [{:keys [r]}]  (* PI (pow r 2)))

Friday, May 17, 13

Page 58: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Multimethods

(defmulti circumference :kind :default :polygon)

(defmethod circumference :polygon  [{:keys [vertices]}]  (reduce + (map distance vertices (drop 1 (cycle vertices)))))

(defmethod circumference :rectangle  [{:keys [a b]}]  (* 2 (+ a b)))

Friday, May 17, 13

Page 59: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Multimethods(defmulti draw-shape  (fn [shape canvas] [(:kind shape) (:type canvas)]))

(defmethod draw-shape :default   [shape canvas]  (str "Drawing " (:kind shape) " on " (:type canvas)))

(defmethod draw-shape [:circle :print-canvas]  [shape canvas]  "Printing a circle")

(defmethod draw-shape [:rectangle :display-canvas]  [shape canvas]  "Showing a rectangle")

Friday, May 17, 13

Page 60: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2011 innoQ Deutschland GmbH

defrecord, de#ype

Friday, May 17, 13

Page 61: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Map

Record

Type

Function

Multimethod

Protocol

Friday, May 17, 13

Page 62: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

defrecord

Supports map access

Flexible & extensible

Convenience functions

Better performance

Platform integration

Protocol support

No structural sharing

Code overhead

Friday, May 17, 13

Page 63: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

de#ype

No generic overhead

Convenience functions

Best performance

Platform integration

Protocol support

No structural sharing

No map access

Static & !xed

Code overhead

Friday, May 17, 13

Page 64: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Protocols(defprotocol Shape  (area [shape])  (circumference [shape]))

(defrecord Rectangle [vertices]  Shape  (area [shape] ...)  (circumference [shape] ...))  (defrecord Circle [center r]  Shape  (area [shape] ...)  (circumference [shape] ...))

Friday, May 17, 13

Page 65: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Protocols(defprotocol ShapeStorage  (read-from [storage])  (write-to [storage shape]))

(extend-protocol ShapeStorage  XmlStorage    (read-from [storage] ...)    (write-to [storage shape] ...)  CouchDB    (read-from [storage] ...)    (write-to [storage shape] ...))

(extend-protocol ShapeStorage  String    (read-from [storage] ...)    (write-to [storage shape] ...))

Friday, May 17, 13

Page 66: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Protocols

Performance

Grouping

Platform integration

Limited dispatch(single arg, type-based)

Friday, May 17, 13

Page 67: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Roadmap Recommendation1

Namespaces, Functions,Persistent Data Structures

2 Multimethods

3defrecorddefprotocol

4 de!ype

Friday, May 17, 13

Page 68: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Summary

Friday, May 17, 13

Page 69: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Functional programmingis di"erent (for a reason)

Friday, May 17, 13

Page 70: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Question your own knowledge

Friday, May 17, 13

Page 71: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Embrace data structures

Friday, May 17, 13

Page 72: Clojure for OOP folks - Amazon S3s3-eu-west-1.amazonaws.com/presentations2013/30...A practical Lisp variant for the JVM Functional programming Dynamic Typing Full-featured macro system

© 2012 innoQ Deutschland GmbH

Thanks!

Q&A

Stefan [email protected]@stilkov

innoQ Deutschland GmbH

http://www.innoq.com

Krischerstr. 10040789 Monheim am RheinGermanyPhone: +49 2173 3366-0

innoQ Schweiz GmbH

[email protected]

Gewerbestr. 11CH-6330 ChamSwitzerlandPhone: +41 41 743 0116

Friday, May 17, 13