66
Dendrology Brandon Bloom

Software Dendrology by Brandon Bloom

Embed Size (px)

DESCRIPTION

As Clojure programmers, our software is full of trees. Both the values we manipulate and the code we manipulate them with, are made from trees. It's all to easy to get caught up in a project and miss the forest for the trees, but how often have you missed the trees for the forest? This presentation is an exploration of trees from a unique perspective that will hopefully inform your thinking and lead your program design out of the woods.

Citation preview

Page 1: Software Dendrology by Brandon Bloom

!

Dendrology Brandon Bloom

Page 2: Software Dendrology by Brandon Bloom

!

Dendrology Brandon Bloom

Page 3: Software Dendrology by Brandon Bloom

bbloom: better ways to analyze and process trees is a bit of a new obsession of mine :-) gfredericks: clojurebot: bbloom is a dendrologist clojurebot: Alles klar

once upon a time in #clojure…

Page 4: Software Dendrology by Brandon Bloom

Assumptions

Data

Immutability

Values

Page 5: Software Dendrology by Brandon Bloom
Page 6: Software Dendrology by Brandon Bloom
Page 7: Software Dendrology by Brandon Bloom
Page 8: Software Dendrology by Brandon Bloom

A

B C D

E F G

Page 9: Software Dendrology by Brandon Bloom

A

B C D

E F G

Page 10: Software Dendrology by Brandon Bloom

A

B C D

E F G

Page 11: Software Dendrology by Brandon Bloom

A B C D

Page 12: Software Dendrology by Brandon Bloom

A

B C

D

Page 13: Software Dendrology by Brandon Bloom

A

B C

D D

Page 14: Software Dendrology by Brandon Bloom

A

B C

D

Page 15: Software Dendrology by Brandon Bloom

A

B C

D

Page 16: Software Dendrology by Brandon Bloom
Page 17: Software Dendrology by Brandon Bloom
Page 18: Software Dendrology by Brandon Bloom

the of allPointer cycles are root evil.tail

Page 19: Software Dendrology by Brandon Bloom

Pointer cycles are evil.

Page 20: Software Dendrology by Brandon Bloom

A

B C

D

B[D]⇒B[E]

Page 21: Software Dendrology by Brandon Bloom

A

B C

D

B[D]⇒B[E]

A’

B’

E

Page 22: Software Dendrology by Brandon Bloom

A

B C

D

B[D]⇒B[E]

Page 23: Software Dendrology by Brandon Bloom

A

B C

D

B[D]⇒B[E]

A

B C

D

B[D]⇒B[E]

A’

B’ C’

E

Page 24: Software Dendrology by Brandon Bloom

D

G

A

B C

E F H I J

Page 25: Software Dendrology by Brandon Bloom

D

G

A

B C

E F H I J

G⇒G’

Page 26: Software Dendrology by Brandon Bloom

D’

G’

A’

B’ C’

E’ F’ H’ I’ J’

G⇒G’

Page 27: Software Dendrology by Brandon Bloom

Pointer are evil. cycles

Page 28: Software Dendrology by Brandon Bloom

Pointer are evil.s

Page 29: Software Dendrology by Brandon Bloom

A

B C

D

B⇒B’

Page 30: Software Dendrology by Brandon Bloom

A

B C

D

B⇒B’

A’

B’

Page 31: Software Dendrology by Brandon Bloom

A

B C

D

B⇒B’

A’

B’

Page 32: Software Dendrology by Brandon Bloom

A

B C

D

B⇒B’

A’

B’

Page 33: Software Dendrology by Brandon Bloom

A

B C

D

B⇒B’

A’

B’

B’⇒B’’

A’’

B’’

Page 34: Software Dendrology by Brandon Bloom
Page 35: Software Dendrology by Brandon Bloom

A

B C

D

B⇒B’

A’

B’

B’⇒B’’

A’’

B’’

Page 36: Software Dendrology by Brandon Bloom

Let’s talk about pointers and identities.

Page 37: Software Dendrology by Brandon Bloom

static byte memory[MEMORY_SIZE];!!template <class T>!class Pointer {!!public:!! Pointer(long p) {! _p = p;! }!! T deref() const {! return !@#$%(memory + _p);! }!! Pointer<T> add(int n) const {! return Pointer(_p + n * sizeof(T));! }!!private:!! long _p;!!};

Page 38: Software Dendrology by Brandon Bloom

static byte memory[MEMORY_SIZE];!!template <class T>!class Reference {!!public:!! Reference(long p) {! _p = p;! }!! T deref() const {! return !@#$%(memory + _p);! }!!!!!!private:!! long _p;!!};

Page 39: Software Dendrology by Brandon Bloom

!!template <class T>!class Reference {!!public:!! Reference(long p) {! _p = p;! }!! T deref() const {! return !@#$%(memory + _p);! }!!!!!!private:!! long _p;!!};

Page 40: Software Dendrology by Brandon Bloom

template <class T>!class Reference {!!public:!! Reference(long p, byte *memory) {! _p = p;! _memory = memory;! }!! T deref() const {! return !@#$%(_memory + _p);! }!!private:!! long _p;! long _memory;!!};

Page 41: Software Dendrology by Brandon Bloom

template <class T>!class Reference {!!public:!! Reference(long p) {! _p = p;! }!! T deref(const byte *const memory) const {! return !@#$%(memory + _p);! }!!private:!! long _p;!!};

Page 42: Software Dendrology by Brandon Bloom

(defprotocol IDeref! (deref [this]))

(deftype Reference [p]! IDerefIn! (deref-in [_ memory]! (!$%&* memory p)))

(defprotocol IDerefIn! (deref-in [this context]))

Page 43: Software Dendrology by Brandon Bloom

(deftype DbRef [table id]! (deref-in [_ db]! (get-row db table id)))!!(let [brandon (DbRef. :users 5)]! (deref-in brandon *db*))!!(defn get-user [db id]! (get-row db :users id))!!(let [brandon 5]! (get-user *db* brandon)

Page 44: Software Dendrology by Brandon Bloom

"http://example.com/api/users/5”

Page 45: Software Dendrology by Brandon Bloom

[:user 5]

Page 46: Software Dendrology by Brandon Bloom

5

Page 47: Software Dendrology by Brandon Bloom

Context is King

Page 48: Software Dendrology by Brandon Bloom

(def x "top-level")!!(fn []! x! (let [x "local"]! x))!

cljs.user.x = "top-level";!!function () {! cljs.user.x;! var x = "local";! return x;!}

Symbols: The Original Identities

var

local symbol resolved using context!

Page 49: Software Dendrology by Brandon Bloom

(def x "top-level")!!(fn []! x! (let [x "local"]! x))!

cljs.user.x = "top-level";!!function () {! cljs.user.x;! var x = "local";! return x;!}

Context: Not Just For Identities

statement

tail position contextual return!

Page 50: Software Dendrology by Brandon Bloom

(def vector-tree! ["A" ["B" ["E"] ["F"]] ["C"] ["D" ["G"]]])

A

B C D

E F G

(def tree! {:label "A"! :children [{:label "B"! :children [{:label "E"}! {:label "F"}]}! {:label "C"}! {:label "D"! :children [{:label "G"}]}]})

Page 51: Software Dendrology by Brandon Bloom

(defn annotate-depth [node]!!!!!!!!!

A

B C D

E F G

0!!

1!!

2

! (letfn [(f [node depth]! (let [d (inc depth)! annotate-child #(f % d)]! (-> node! (assoc :depth depth)! (update-in! [:children]! (mapv annotate-child %)))))]! (f node 0)))

Page 52: Software Dendrology by Brandon Bloom

A

B C D

E F G

2

2

2 2

1 2

2

(defn annotate-max-depth [node]!!!!!!!!!!

! (let [{:keys [children]} node]! (if (seq children)! (let [children*! (mapv annotate-max-depth children)]! (assoc node! :max-depth (apply max! (map :max-depth children*))! :children children*))! (assoc node :max-depth (:depth node)))))

Page 53: Software Dendrology by Brandon Bloom

A

B C D

E F G

0

1

2 3

4 5

6

(defn print-depth-first-recursive [node]! (letfn [(f [node index]! (println index (:label node))! (loop [nodes (:children node)! i index]! (if (seq nodes)! (recur (next nodes)! (f (first nodes) (inc i)))! i)))]! (f node 0))! nil)

0 A 1 B 2 E 3 F 4 C 5 D 6 G

Page 54: Software Dendrology by Brandon Bloom

A

B C D

E F G

0

1

2 3

4 5

6

(defn number-depth-first-recursive [node]! (letfn [(f [node index]! (let [[max-index children*]! (reduce (fn [[i children] child]! (let [child* (f child (inc i))! i* (:max-index child*)]! [i* (conj children child*)]))! [index []]! (:children node))]! (assoc node! :index index! :children children*! :max-index max-index)))]! (f node 0)))

Page 55: Software Dendrology by Brandon Bloom

A

B C D

E F G

0

1

2 3

4 5

6

(defn number-depth-first-stateful [node]! (let [index (atom 0)]! ((fn rec [n]! (let [i @index]! (swap! index inc)! (-> n! (assoc :index i)! (update-in [:children] #(mapv rec %)))))! node)))

Page 56: Software Dendrology by Brandon Bloom

(defn print-depth-first-iterative [node]! (loop [index 0! nodes (list node)]! (when (seq nodes)! (let [[node & nodes*] nodes]! (println index (:label node))! (recur (inc index)! (concat (:children node)! nodes*))))))

A

B C D

E F G

0

1

2 3

4 5

6

Page 57: Software Dendrology by Brandon Bloom

(defn print-breadth-first-iterative [node]! (loop [index 0! nodes (list node)]! (when (seq nodes)! (let [[node & nodes*] nodes]! (println index (:label node))! (recur (inc index)! (concat nodes*! (:children node)))))))

A

B C D

E F G

0

1

4 5

2 3

6

0 A 1 B 2 C 3 D 4 E 5 F 6 G

Page 58: Software Dendrology by Brandon Bloom

A

B C D

E F G

0

1

2 3

4 5

6

(defn make-zipper [root]! (z/zipper (fn branch? [n]! true)! :children! (fn make-node [n children]! (assoc n :children (vec children)))! root))

Page 59: Software Dendrology by Brandon Bloom

A

B C D

E F G

0

1

2 3

4 5

6

(defn number-depth-first-zipper [node]! (loop [index 0! loc (make-zipper node)]! (if (z/end? loc)! (z/root loc)! (let [loc* (z/edit loc assoc :index index)]! (recur (inc index) (z/next loc*))))))

complete context as data!

Page 60: Software Dendrology by Brandon Bloom

Melt your brain: !Breadth-first numbering!Chris Okasaki !Backtracking Iterators!Jean-Christophe Filliâtre

A

B C D

E F G

0

1

4 5

2 3

6

Page 61: Software Dendrology by Brandon Bloom

Carefully consider: identities + contexts

Page 62: Software Dendrology by Brandon Bloom
Page 63: Software Dendrology by Brandon Bloom
Page 64: Software Dendrology by Brandon Bloom

EXTRA SLIDES PAST HERE

Page 65: Software Dendrology by Brandon Bloom

let cyclic = let x = 0 : y! y = 1 : x! in x!!take 10 cyclic!-- [0,1,0,1,0,1,0,1,0,1]

(def cyclic! (letfn [(x [] (cons 0 (lazy-seq (y))))! (y [] (cons 1 (lazy-seq (x))))]! (x)))!!(take 10 cyclic)!;=> (0 1 0 1 0 1 0 1 0 1)

A note about laziness

Page 66: Software Dendrology by Brandon Bloom

(def cyclic! (letfn [(x [] (cons 0 (lazy-seq (y))))! (y [] (cons 1 (lazy-seq (x))))]! (x)))!!(take 10 cyclic)!;=> (0 1 0 1 0 1 0 1 0 1)

(def cyclic! (letfn [(x [] (cons 0 (new clojure.lang.LazySeq! (fn [] (y)))))! (y [] (cons 1 (new clojure.lang.LazySeq! (fn [] (x)))))]! (x)))