Software Dendrology by Brandon Bloom
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share

Software Dendrology by Brandon Bloom

  • 2,313 views
Uploaded on

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......

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.

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
2,313
On Slideshare
504
From Embeds
1,809
Number of Embeds
6

Actions

Shares
Downloads
4
Comments
0
Likes
1

Embeds 1,809

http://www.hakkalabs.co 1,793
http://tech.d8p.it 8
http://hakka-staging.herokuapp.com 4
http://hakka-staging-2.herokuapp.com 2
http://g33ktalk.com 1
https://hakka-staging-2.herokuapp.com 1

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. ! Dendrology Brandon Bloom
  • 2. ! Dendrology Brandon Bloom
  • 3. once upon a time in #clojure… 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
  • 4. Assumptions Data Immutability Values
  • 5. A B E C F D G
  • 6. A B E C F D G
  • 7. A B E C F D G
  • 8. A B C D
  • 9. A B C D
  • 10. A B C D D
  • 11. A B C D
  • 12. A B C D
  • 13. Pointer cycles are the root of all evil. tail
  • 14. Pointer cycles are evil.
  • 15. B[D] B[E] A B C D
  • 16. B[D] B[E] A B A’ C D B’ E
  • 17. B[D] B[E] A B C D
  • 18. B[D] B[E] A B A’ C D B’ C’ E
  • 19. A B E C F G D H I J
  • 20. G G’ A B E C F G D H I J
  • 21. G G’ A’ B’ E’ C’ F’ G’ D’ H’ I’ J’
  • 22. Pointer cycles are evil.
  • 23. Pointers are evil.
  • 24. B B’ A B C D
  • 25. B B’ A B A’ C D B’
  • 26. B B’ A B A’ C D B’
  • 27. B B’ A B A’ C D B’
  • 28. B B’ A A’’ A’ C D B’ B’’ B’ B’’
  • 29. B B’ A A’’ A’ C D B’ B’’ B’ B’’
  • 30. Let’s talk about pointers and identities.
  • 31. 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;! ! };
  • 32. 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;! ! };
  • 33. ! ! template <class T>! class Reference {! ! public:! ! Reference(long p) {! _p = p;! }! ! T deref() const {! return !@#$%(memory + _p);! }! ! ! ! ! ! private:! ! long _p;! ! };
  • 34. 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;! ! };
  • 35. template <class T>! class Reference {! ! public:! ! Reference(long p) {! _p = p;! }! ! T deref(const byte *const memory) const {! return !@#$%(memory + _p);! }! ! private:! ! long _p;! ! };
  • 36. (defprotocol IDeref! (deref [this])) (defprotocol IDerefIn! (deref-in [this context])) (deftype Reference [p]! IDerefIn! (deref-in [_ memory]! (!$%&* memory p)))
  • 37. (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)
  • 38. "http://example.com/api/users/5”
  • 39. [:user 5]
  • 40. 5
  • 41. Context is King
  • 42. Symbols: The Original Identities (def x "top-level")! cljs.user.x = "top-level";! ! ! (fn []! v a r x! (let [x "local"]! x))! function () {! cljs.user.x;! var x = "local";! return x;! } loc al b o l re s o l v e d sym g c o n te x t ! us i n
  • 43. Context: Not Just For Identities (def x "top-level")! cljs.user.x = "top-level";! ! ! (fn []! s t a te me n t x! (let [x "local"]! x))! t ai l p o si t io n function () {! cljs.user.x;! var x = "local";! return x;! } x t u a l re t u r n ! c o n te
  • 44. A B E C F D G (def vector-tree! ["A" ["B" ["E"] ["F"]] ["C"] ["D" ["G"]]]) (def tree! {:label "A"! :children [{:label "B"! :children [{:label "E"}! {:label "F"}]}! {:label "C"}! {:label "D"! :children [{:label "G"}]}]})
  • 45. A 0! ! 1! B C D ! 2 ! E F G (defn annotate-depth [node]! ! (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)))
  • 46. 2 2 2 ! E 2 1 B F A C 2 D 2 G (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)))))
  • 47. 0 1 2 E 3 4 B F A C 5 D 6 G 0A 1B 2E 3F 4C 5D 6G (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)
  • 48. 0 1 2 E 3 4 B F A C 5 D 6 G (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)))
  • 49. 0 1 2 E 3 4 B F A C 5 D 6 G (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)))
  • 50. 0 1 2 E 3 4 B F A C 5 D 6 G (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*))))))
  • 51. 0 1 4 E 5 2 B F A C 3 D 6 G 0A 1B 2C 3D 4E 5F 6G (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)))))))
  • 52. 0 1 2 E 3 4 B F A C 5 D 6 G (defn make-zipper [root]! (z/zipper (fn branch? [n]! true)! :children! (fn make-node [n children]! (assoc n :children (vec children)))! root))
  • 53. 0 1 2 E 3 4 B F A C 5 D 6 G (defn number-depth-first-zipper [node]! (loop [index 0! te c o n te x t c om p le loc (make-zipper node)]! as d at a! (if (z/end? loc)! (z/root loc)! (let [loc* (z/edit loc assoc :index index)]! (recur (inc index) (z/next loc*))))))
  • 54. 0 1 4 E 5 2 B A C F 3 D 6 G Melt your brain: ! Breadth-first numbering! Chris Okasaki ! Backtracking Iterators! Jean-Christophe Filliâtre
  • 55. Carefully consider: identities + contexts
  • 56. EXTRA SLIDES PAST HERE
  • 57. A note about laziness 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)
  • 58. (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)))