Slide 1

Slide 1 text

Working with data structures Friday, October 11, 13

Slide 2

Slide 2 text

simple data • numbers • keywords • symbols • strings, characters Friday, October 11, 13

Slide 3

Slide 3 text

[], ‘(), #{}, {} Collections Friday, October 11, 13

Slide 4

Slide 4 text

Lists '(1 2 3 4) '("clojure" "scala" "erlang") Friday, October 11, 13

Slide 5

Slide 5 text

Vectors [1 2 3 4] ["clojure" "scala" "erlang"] Friday, October 11, 13

Slide 6

Slide 6 text

Sets #{1 2 3 4} #{"clojure" "scala" "erlang"} Friday, October 11, 13

Slide 7

Slide 7 text

{:id 42 :name "Maxi" :language "clojure"} Maps Friday, October 11, 13

Slide 8

Slide 8 text

Collections are Immutable Friday, October 11, 13

Slide 9

Slide 9 text

doesn’t immutability require a lot of copying? Friday, October 11, 13

Slide 10

Slide 10 text

yes, but there’s a trick Friday, October 11, 13

Slide 11

Slide 11 text

Persistent data structures Friday, October 11, 13

Slide 12

Slide 12 text

Copy only what is needed through structural sharing Friday, October 11, 13

Slide 13

Slide 13 text

“just” “a” “list” Friday, October 11, 13

Slide 14

Slide 14 text

“just” “a” “list” “i’m” Friday, October 11, 13

Slide 15

Slide 15 text

hmm, but that’s still less efficient than mutation, right? Friday, October 11, 13

Slide 16

Slide 16 text

Transients • provide mutability where performance is critical • enforce thread isolation • convert from/to persistent ds in O(1) Friday, October 11, 13

Slide 17

Slide 17 text

associative data structurues [], {} Friday, October 11, 13

Slide 18

Slide 18 text

Basic operations Friday, October 11, 13

Slide 19

Slide 19 text

get retrieve value by key (get {:hi :there} :hi) ;; => :there (get [1 2 3] 1) ;; => [2] Friday, October 11, 13

Slide 20

Slide 20 text

get-in retrieve nested value by key-seq (get-in {:lang {:name clojure"}} [:lang :name]) ;; => "clojure" (get-in [[1 2] [3 4]] [0 1]) ;; => 2 Friday, October 11, 13

Slide 21

Slide 21 text

(assoc {} :hi :there) ;;=> {:hi :there} assoc add new key value pair (assoc [] 0 1) ;;=> [1] Friday, October 11, 13

Slide 22

Slide 22 text

dissoc remove key value pair (map only) (dissoc {:hi there} :hi) ;;=> {} Friday, October 11, 13

Slide 23

Slide 23 text

Utility functions Friday, October 11, 13

Slide 24

Slide 24 text

keys/vals get the keys/values (keys {:a :b :c :d}) ;;=> (:a :c) (vals {:a :b :c :d}) ;;=> (:b :d) Friday, October 11, 13

Slide 25

Slide 25 text

merge merge maps, overwriting values right to left (merge {:a 1 :b 2 :c 3} {:b 3 :c 4} {:c 5}) ;; => {:a 1, :c 5, :b 3} Friday, October 11, 13

Slide 26

Slide 26 text

merge-with merge maps, overwriting is managed by fn (merge-with (fn [a b] a) {:a 1 :b 2 :c 3} {:b 3 :c 4} {:c 5}) ;; => {:a 1, :c 3, :b 2} Friday, October 11, 13

Slide 27

Slide 27 text

[], ‘(), #{}, {} sequential data structures Friday, October 11, 13

Slide 28

Slide 28 text

Basic operations Friday, October 11, 13

Slide 29

Slide 29 text

cons builds a cons cell (ie, add before first element) (cons 1 [2 3]) ;;=> (1 2 3) (cons 1 '(2 3)) ;;=> (1 2 3) Friday, October 11, 13

Slide 30

Slide 30 text

conj add element to a sequence place of addition depends on sequence type (conj [2 3] 1) ;;=> [2 3 1] (conj ‘(2 3) 1) ;;=> (1 2 3) Friday, October 11, 13

Slide 31

Slide 31 text

(concat [1 2] ‘(3 4)) ;;=> (1 2 3 4) concat concatenate sequences Friday, October 11, 13

Slide 32

Slide 32 text

disj remove element from a set sets only! (disj #{:a :b :c} :a) ;;=> {:b :c} Friday, October 11, 13

Slide 33

Slide 33 text

seq convert any collection to a seq returns nil for nil, empty collections Friday, October 11, 13

Slide 34

Slide 34 text

Utility functions Friday, October 11, 13

Slide 35

Slide 35 text

partition divide a sequence into parts parts may overlap (optional) (partition 2 [1 2 3 4 5]) ;;=> ((1 2) (3 4)) Friday, October 11, 13

Slide 36

Slide 36 text

flatten convert any nested seq into a flat list (flatten [1 [2] [3 4]]) ;;=> (1 2 3 4) Friday, October 11, 13

Slide 37

Slide 37 text

frequencies take a seq and return the number of occurrences for each element (frequencies [:a :v :d :v :a]) ;;=> {:a 2, :v 2, :d 1} Friday, October 11, 13

Slide 38

Slide 38 text

Sequence predicates Friday, October 11, 13

Slide 39

Slide 39 text

every? true if all members satisfy the predicate (every? even? [2 4 6 8]) ;;=> true (every? even? [2 4 7 8]) ;;=> false Friday, October 11, 13

Slide 40

Slide 40 text

some true if at least one member satisfies the predicate not-any? as complement. (some even? [1 4 5 7]) ;;=> true (some even? [1 3 5 7]) ;;=> nil Friday, October 11, 13

Slide 41

Slide 41 text

comprehensions Friday, October 11, 13

Slide 42

Slide 42 text

for • looks like iteration, but is list comprehension • not intended for side effects • carthesian product of multiple lists • powerful possibilities for filtering/constraining Friday, October 11, 13

Slide 43

Slide 43 text

examples (for [x (range 3) y (range 3)] [x y]) ;;=> ([0 0] [0 1] [0 2] [1 0] ;; [1 1] [1 2] [2 0] [2 1] [2 2]) (for [x (range 3) y (range 3) :while (< y x)] [x y]) ;; => ([1 0] [2 0] [2 1]) Friday, October 11, 13

Slide 44

Slide 44 text

doseq • intended for side effects • similar filtering/constraining possibilities as for • always returns nil! Friday, October 11, 13

Slide 45

Slide 45 text

example (doseq [x (range 3) y (range 3) :while (< y x)] (println [x y])) ;; [1 0] ;; [2 0] ;; [2 1] ;;=> nil Friday, October 11, 13

Slide 46

Slide 46 text

Combinators Friday, October 11, 13

Slide 47

Slide 47 text

consider the following Java code Friday, October 11, 13

Slide 48

Slide 48 text

public static List incByOne(List input){ List mapped = new ArrayList(); " for(int i:input){ " " mapped.add(i + 1); " } " return mapped; } Friday, October 11, 13

Slide 49

Slide 49 text

public static List incByOne(List input){ List mapped = new ArrayList(); " for(int i:input){ " " mapped.add(i + 1); " } " return mapped; } Boilerplate Code Friday, October 11, 13

Slide 50

Slide 50 text

public static List incByOne(List input){ List mapped = new ArrayList(); " for(int i:input){ " " mapped.add(i + 1); " } " return mapped; } Hard-coded Functionality Friday, October 11, 13

Slide 51

Slide 51 text

some guava might help... Friday, October 11, 13

Slide 52

Slide 52 text

Collections2.transform(input, new Function(){ public Integer apply(final Integer i){ return i + 1; } }); Friday, October 11, 13

Slide 53

Slide 53 text

much better, but... Friday, October 11, 13

Slide 54

Slide 54 text

Collections2.transform(input, new Function(){ public Integer apply(final Integer i){ return i + 1; } }); Still too much Boilerplate Friday, October 11, 13

Slide 55

Slide 55 text

enter: clojure Friday, October 11, 13

Slide 56

Slide 56 text

(map inc input) Friday, October 11, 13

Slide 57

Slide 57 text

map f [a,b,c,...] [f(a),f(b),f(c),...] Friday, October 11, 13

Slide 58

Slide 58 text

examples (map inc [1 2 3 4]) ;;=> (2 3 4 5) (map :id [{:id 2 :name "Maxi"} {:id 4 :name "Alex"}]) ;;=> (2 4) Friday, October 11, 13

Slide 59

Slide 59 text

mapcat f [a,b,c,...] (concat f(a) f(b) f(c) ...) Friday, October 11, 13

Slide 60

Slide 60 text

examples (mapcat list [:a :b :c] [1 2 3]) ;;=> (:a 1 :b 2 :c 3) (mapcat (fn [x] (repeat x x)) [1 2 3]) ;;=> (1 2 2 3 3 3) Friday, October 11, 13

Slide 61

Slide 61 text

filter [a,b,c,d,e,...] predicate (true? (pred x)) [a,c,e,...] Friday, October 11, 13

Slide 62

Slide 62 text

remove [a,b,c,d,e,...] (false? (pred x)) predicate [a,c,e,...] Friday, October 11, 13

Slide 63

Slide 63 text

examples (filter even? [1 2 3 4]) ;;=> (2 4) (remove nil? [1 nil 3 nil]) ;;=> (1 3) Friday, October 11, 13

Slide 64

Slide 64 text

reduce f acc(i) := f(acc(i-1), x) acc [b,c,d,e,...] acc(0) := a Friday, October 11, 13

Slide 65

Slide 65 text

examples (reduce + [1 2 3 4]) ;;=> 10 (reduce conj ‘() [1 2 3 4]) ;;=> (4 3 2 1) Friday, October 11, 13

Slide 66

Slide 66 text

reductions [b,c,d,e,...] acc(i) := f(acc(i-1), x) [acc(0), acc(1), ...] acc(0) := a f Friday, October 11, 13

Slide 67

Slide 67 text

examples (reductions + [1 2 3 4]) ;;=> (1 3 6 10) (reductions conj ‘() [1 2 3 4]) ;;=> (() (1) (2 1) (3 2 1) (4 3 2 1)) Friday, October 11, 13

Slide 68

Slide 68 text

From State to Recursion Friday, October 11, 13

Slide 69

Slide 69 text

imperative summing public int sum(Iterable c){ int sum = 0; for(int i:c){ sum += i; } return sum; } Friday, October 11, 13

Slide 70

Slide 70 text

this won’t fly in a fp context. Friday, October 11, 13

Slide 71

Slide 71 text

this won’t fly in a fp context. recursion to the rescue! Friday, October 11, 13

Slide 72

Slide 72 text

recursive summing (defn recursive-sum [[head & tail]] (if (empty? tail) (or head 0) (+ head (recursive-sum tail)))) Friday, October 11, 13

Slide 73

Slide 73 text

recursive summing (recursive-sum [1 2 3 4 5]) ;;=> 15 Friday, October 11, 13

Slide 74

Slide 74 text

wait a minute... (recursive-sum (range 10000)) ;; StackOverflowError clojure.lang.LazySeq.sval (LazySeq.java:42) Friday, October 11, 13

Slide 75

Slide 75 text

where’s the problem? (defn recursive-sum [[head & tail]] (if (empty? tail) (or head 0) (+ head (recursive-sum tail)))) Friday, October 11, 13

Slide 76

Slide 76 text

(defn recursive-sum [[head & tail]] (if (empty? tail) (or head 0) (+ head (recursive-sum tail)))) where’s the problem? Friday, October 11, 13

Slide 77

Slide 77 text

tail recursion to the rescue! Friday, October 11, 13

Slide 78

Slide 78 text

tail-recursive summing i (defn recursive-sum-tc ([[head & tail] acc] (if (empty? tail) (+ acc head) (recursive-sum-tc tail (+ acc head)))) ([coll] (recursive-sum-tc coll 0))) Friday, October 11, 13

Slide 79

Slide 79 text

tail-recursive summing ii (defn recursive-sum-tc [coll] (loop [[head & tail] coll acc 0 ] (if (nil? head) acc (recur tail (+ acc head))))) Friday, October 11, 13