1 / 47

PPL

PPL. Pairs, lists and data abstraction. Data Abstraction?. An interface: separate implementation from usage Think of the Map interface in Java: we know how to use it, but we don’t know how it’s implemented . Motivation: better software design, modularity, less maintenance and more!.

dannon
Download Presentation

PPL

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. PPL Pairs, lists and data abstraction

  2. Data Abstraction? • An interface: separate implementation from usage • Think of the Map interface in Java: we know how to use it, but we don’t know how it’s implemented. • Motivation: better software design, modularity, less maintenance and more!

  3. Data Abstractions in Scheme? • Of course, but first we need to present 2 new data types in Scheme: • Pairs • Lists

  4. Pairs • Combines two data entities into a single unit • Scheme provides built in primitives: • Value constructor: cons • Selectors: car, cdr • Identify predicate: pair? • Equality: equal?

  5. Pairs > (define x (cons 1 2)) > (car x) 1 > (cdr x) 2 > x (1 . 2) “toString” of pair

  6. Pairs Each data entity can be anything! > (define y (cons x (quote a))) > (car y) (1 . 2) > (cdr y) 'a > y ((1 . 2) . a) Recall that x is the pair (cons 1 2)

  7. Pairs Do not confuse (cons 1 2) with (1 . 2) !! 1st is a Scheme expression (syntax) and 2nd is the ‘toString’ of the value

  8. Pairs Type constructor: PAIR [T1*T2 -> PAIR(T1,T2)] (λ (x y) (cons x y))

  9. Recursive Pairs (define rec-pairs (λ (n) (if (= n 1) 1 (cons n (rec-pairs (- n 1)))))) > (rec-pairs 5) (5 4 3 2 . 1) ;(cons 5 (cons 4 (cons 3 (cons 2 (cons 1)))))

  10. Recursive Pairs We can also represent binary trees! (cons (cons 1 2) (cons (cons 3 4) (cons 5 6))) ((1 . 2) (3 . 4) 5 . 6)

  11. Recursive Pairs • We have trees! How about searching a tree? (define member ? (lambda (el pair) (cond ((and (pair? (car pair)) (member? el (car pair))) #t) ((eq? el (car pair)) #t) ((and (pair? (cdr pair)) (member? el (cdr pair))) #t) ((eq? el (cdr pair)) #t) (else #f))))

  12. Recursive Pairs • How about counting number of leaves? (define count-leaves (λ (t) (if (not (pair? t)) 1 (+ (count-leaves (car t)) (count-leaves (cdr t))))))

  13. Visual Representation

  14. Lists • Finite sequence<v1, …, vn>(v1 … vn) • v1 is head, (v2 … vn) is tail • Value constructors: cons and list • Empty: (list) • Non-empty: • (cons head tail) – tail must be a list! • (list e1 … en)

  15. Lists • Both will create the same list: (list 1 2 3) (cons 1 (cons 2 (cons 3 (list))))

  16. Lists • Selectors: • car: head • cdr: tail • Predicates: • list? • null? • equal?

  17. Visual Representation

  18. Lists and Types • Homogenous • Examples: (1 2 3), ((1 2) (3)) • LIST(Number), LIST(T), … • Heterogeneous • Examples: (1 #f 3), ((1 2) 3) • LIST

  19. Useful List Operations car + cdr: > (define x (list 5 6 8 2)) > (car x) 5 > (cdr x) (6 8 2) > (car (cdr x)) 6 > (cadr x) 6 > (cddr x) (8 2)

  20. Selector: list-ref nth element of a list: (define list-ref (λ (ln) (if (= n 0) (car l) (list-ref (cdr l) (- n 1))))) (define squares (list 1 4 9 16 25 36)) (list-ref squares 4)

  21. Operator: length (define length (λ (l) (if (null? l) 0 (+ 1 (length (cdr l)))))) (define squares (list 1 4 9 16 25 36)) (length squares) 6

  22. Iterative length (define length (λ (l) (letrec ((iter (λ (l c) (if (null? l) c (iter (cdr l) (+ c 1)))))) (iter l 0))))

  23. Operator: append (define append (λ (l1 l2) (if (null? l1) l2 (cons (car l1) (append (cdr l1) l2))))) (append (list 1 2 3) (list 3 4))

  24. Iterative append ;; Type: [LIST * LIST -> LIST] (define append (λ (l1 l2) (letrec ((iter (λ (l1 l2 c) (if (null? l1) (c l2) (iter (cdr l1) l2 (λ (app-cdr-l1) (c (cons (car l1) app-cdr-l1)))))))) (iter l1 l2 (lambda (x) x)))))

  25. Constructor make-list Builds a list of given with given values (define make-list (λ (l v) (if (= l 0) (list) (cons v (make-list (- l 1) v)))))

  26. Using Lists to Represent Trees • Very much like pairs, but better: • Empty tree () • Leaf is just value • Non-empty tree – non-empty list • Example: (1 (2 3)) is the tree:

  27. Using Lists to Represent Trees • How can we add data to non-leaf nodes? (i.e. labeled tree) : each node is also a list! • ((1) ((2) (3))) • Now we can create labled trees: • (1 (0) (3 (2) (4)))

  28. Leaves Count • Unlabeled tree (define count-leaves (λ (t) (cond ((null? t) 0) ((not (list? t)) 1) (else (+ (count-leaves (car t)) (count-leaves (cdr t)))))))

  29. Type Correctness with Pairs and Lists • cons and list are primitives (not special forms!) • So we need more axioms.

  30. Pairs For every type environment _Tenvand type expressions _S,_S1,_S2: Tenv|- cons:[S1*S2 -> PAIR(S1,S2)] Tenv|- car:[PAIR(S1,S2) -> S1] Tenv|- cdr:[PAIR(S1,S2) -> S2] Tenv|- pair?:[S -> Boolean] Tenv|- equal?:[PAIR(S1,S2)*PAIR(S3,S4) -> Boolean]

  31. Homogenous Lists For every type environment Tenv and type expression S: Tenv|- list:[Empty -> LIST(S)] Tenv|- list:[S* ...*S -> LIST(S)] n >0 Tenv|- cons:[S*LIST(S) -> LIST(S)] Tenv|- car:[LIST(S) -> S] Tenv|- cdr:[LIST(S) -> LIST(S)] Tenv|- null?:[LIST(S) -> Boolean] Tenv|- list?:[S -> Boolean] Tenv|- equal?:[LIST(S)*LIST(S) -> Boolean]

  32. Heterogeneous Lists For every type environment Tenv and type expression S: Tenv|- list:[Empty -> LIST] Tenv|- cons:[S*LIST -> LIST] Tenv|- car:[LIST -> S] Tenv|- cdr:[LIST -> LIST] Tenv|- null?:[LIST -> Boolean] Tenv|- list?:[S -> Boolean] Tenv|- equal?:[LIST*LIST -> Boolean]

  33. What About Data Abstraction? • An interface: separation between usage (client) and implementation (supplier) • Supplier gives getters, setters and other operators, and client uses them. • Order of development: • Client level • Supplier level

  34. ADT • It’s a new type with a difference: type is semantic while ADT is syntactic • Signature of constructor • Signature of operators • Invariants (see later)

  35. So Why start with Pairs and Lists? • Pairs and lists will be our implementation! The client will not know we used pairs and lists, she will just use the operations we give her! • Example next slide

  36. Binary Tree ADT: Constructors Signature: make-binary-tree(l,r) Purpose: Returns a binary tree whose left sub-tree is l and whose right sub-tree is r Type: [Binary-Tree*Binary-Tree -> Binary-Tree] Pre-condition: binary-tree?(l) and binary-tree?(r) Signature: make-leaf(d) Purpose: Returns a leaf binary-tree whose data element is d Type: [T -> Binary-Tree]

  37. Binary Tree ADT: Selectors Signature: left-tree(r), right-tree(r) Purpose: (left-tree <t>): Returns the left sub-tree of the binary-tree <t>. (right-tree <t>): Returns the right sub-tree of the binary-tree <t>. Type: [Binary-Tree -> Binary-Tree] Pre-condition: composite-binary-tree?(t) Signature: leaf-data(r) Purpose: Returns the data element of the leaf binary-tree <t>. Type: [Binary-Tree -> T] Pre-condition: leaf?(t)

  38. Binary Tree ADT: Predicates Signature: leaf?(t) Type: [T -> Boolean] Post-condition: true if t is a leaf -- constructed by make-leaf Signature: composite-binary-tree?(t) Type: [T -> Boolean] Post-condition: true if t is a composite binary-tree -- constructed by make-binary-tree Signature: binary-tree?(t) Type: [T -> Boolean] Post-condition: result = (leaf?(t) or composite-binary-tree?(t) ) Signature: equal-binary-tree?(t1, t2) Type: [Binary-Tree*Binary-Tree -> Boolean]

  39. Binary Tree ADT: Invariants leaf-data(make-leaf(d)) = d left-tree(make-binary-tree(l,r)) = l right-tree(make-binary-tree(l,r)) = r leaf?(make-leaf(d)) = true leaf?(make-binary-tree(l,r)) = false composite-binary-tree?(make-binary-tree(l,r)) = true composite-binary-tree?(make-leaf(d)) = false

  40. Binary Tree ADT: Client Level ;Signature: count-leaves(tree) ;Purpose: Count the number of leaves of ’tree’ ;Type: [binary-Tree -> number] (define count-leaves (lambda (tree) (if (composite-binary-tree? tree) (+ (count-leaves (left-tree tree)) (count-leaves (right-tree tree))) 1)))

  41. Binary Tree ADT: Implementation ;Signature: make-binary-tree(l,r) ;Type: [(LIST union T1)*(LIST union T2) ; -> LIST] ;Pre-condition: binary-tree?(l) ; and binary-tree?(r) (define make-binary-tree (lambda (l r) (list l r))) ;Signature: make-leaf(d) ;Type: [T -> T] (define make-leaf (lambda (d) d)) ;Signature: left-tree(t) ;Type: [LIST -> LIST union T] ;Pre-condition: composite-binary-tree?(t) (define left-tree (lambda (t) (car t))) ;Signature: right-tree(t) ;Type: [LIST -> LIST union T] ;Pre-condition: composite-binary-tree?(t) (define right-tree (lambda (t) (cadr t)))

  42. Binary Tree ADT: Implementation ;Signarture: leaf-data(t) ;Type: [T -> T] ;Pre-condition: leaf?(t) (define leaf-data (lambda (t) t)) ;Signarture: leaf?(t) ;Type: [T -> Boolean] (define leaf? (lambda (t) #t)) ;Signarture: composite-binary-tree?(t) ;Type: [T -> Boolean] (define composite-binary-tree? (lambda (t) (and (list? t) (list? (cdr t)) (null? (cddr t)) (binary-tree? (left-tree t)) (binary-tree? (right-tree t)))

  43. Binary Tree ADT: Invariants Seems ok, but look: > (leaf? (make-leaf (list 5 6))) #t > (has-leaf? (list 5 6) (make-leaf (list 5 6))) #f We have no way to distinct composite leaves from tree… We need a better implementation: tagged-data!

  44. Tagged Data ADT Signature: attach-tag(x,tag) Purpose: Construct a tagged-data value Type: [T*Symbol -> Tagged-data(T)] Signature: get-tag(tagged) Purpose: Select the tag from a tagged-data value Type: [Tagged-data(T) -> Symbol] Signature: get-content(tagged) Purpose: Select the data from a tagged-data value Type: [Tagged-data(T) -> T] Signature: tagged-data?(datum) Purpose: Identify tagged-data values Type: [T -> Boolean] Signature: tagged-by? (tagged,tag) Purpose: Identify tagged-data values Type: [T*Symbol -> Boolean]

  45. Binary Tree ADT: Implementation using Tagged-Data ;Signature: make-binary-tree(l,r) ;Type: [(LIST union T1)*(LIST union T2) ; -> Tagged-data(LIST)] ;Pre-condition: binary-tree?(l) ; and binary-tree?(r) (define make-binary-tree (lambda (l r) (attach-tag (list l r) ’composite-binary-tree))) ;Signature: make-leaf(d) ;Type: [T -> Tagged-data(T)] (define make-leaf (lambda (d) (attach-tag d ’leaf))) ;Signature: left-tree(t) ;Type: [Tagged-data(LIST) ; -> Tagged-data(LIST union T)] ;Pre-condition: composite-binary-tree?(t) (define left-tree (lambda (t) (car (get-content t)))) ;Signature: right-tree(t) ;Type: [Tagged-data(LIST) -> Tagged-data(LIST union T)] ;Pre-condition: composite-binary-tree?(t) (define right-tree (lambda (t) (cadr (get-content t))))

  46. Tagged-Data Implementation • Have you noticed that we didn’t implement the tagged-data ADT? • That’s the whole idea! We are clients! We don’t have to know the implementation! • But we’ll give it anyway… 

  47. Tagged-Data ADT Implementation ;Signature: attach-tag(x,tag) ;Type: [Symbol*T -> PAIR(Symbol, T)] (define attach-tag (λ (x tag) (cons tag x))) ;Signature: get-tag(tagged) ;Type: PAIR(Symbol,T) -> Symbol (define get-tag (λ (tagged) (car tagged))) ;Signature: get-content(tagged) ;Type: [PAIR(Symbol,T) -> T] (define get-content (λ (tagged) (cdr tagged))) ;Signature: tagged-data?(datum) ;Type: [T -> Boolean] (define tagged-data? (λ (datum) (and (pair? datum) (symbol? (car datum))))) ;Signature: tagged-by?(tagged,tag) ;Type: [T*Symbol -> Boolean] (define tagged-by? (λ (tagged tag) (and (tagged-data? tagged) (eq? (get-tag tagged) tag))))

More Related