6.001 SICP Data abstractions Review of abstraction power Pairs, lists, and now trees Elements of a data abstraction Example: rational numbers 6.001 SICP
Example of higher order abstractions (define (filter pred lst) (if (pred (car lst)) (cons (car lst) (filter pred (cdr lst))) (filter pred (cdr lst)))) (define (generate low high) (if (> low high) nil (cons low (generate (+ low 1) high)))) 6.001 SICP
Finding all the primes 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 3 X XX 7 XX 2 X XX 5 XX 6.001 SICP
.. And here’s how to do it! (define (sieve lst) (if (null? lst) nil (cons (car lst) (sieve (filter (lambda (x) (not (divisible? x (car lst)))) (cdr lst)))))) (sieve (generate 2 420)) (2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229 233 239 241 251 257 263 269 271 277 281 293 307 311 313 317 331 337 347 349 353 359 367 373 379 383 389 397 401 409 419) 6.001 SICP
Pairs (2 . 3) Type Definition: Pair<number,number> more generally: Pair<A,B> where A = anytype and B = anytype in most general case Operations: cons, car, cdr, pair? 6.001 SICP
Lists (2 3 4) Type Definition: List<number> more generally (and in more detail) List<C> = Pair<C,List<C>> | null Operations: list, null? copy, append, length, list-ref map, filter, accumulate (HOPs) 2 3 4 6.001 SICP
Trees Type Definition: children or subtrees root 2 4 6 8 Type Definition: Tree<C> = List<Tree<C>> | Leaf<C> Leaf<C> = C Operations: leaf? Examples: countleaves, scaletree 4 2 6 8 6.001 SICP
Tree Procedures A tree is a list; we can use list procedures on them: (define my-tree (list 4 (list 5 7) 2)) (length my-tree) ==> 3 (countleaves my-tree) ==> 4 4 2 5 7 my-tree 6.001 SICP
countleaves Strategy base case: count of an empty tree is 0 base case: count of a leaf is 1 recursive strategy: the count of a tree is the sum of the countleaves of each child in the tree. Implementation: (define (countleaves tree) (cond ((null? tree) 0) ;base case ((leaf? tree) 1) ;base case (else ;recursive case (+ (countleaves (car tree)) (countleaves (cdr tree)))))) (define (leaf? x) (not (pair? x))) 6.001 SICP
countleaves and substitution model (define (countleaves tree) (cond ((null? tree) 0) ;base case ((leaf? tree) 1) ;base case (else ;recursive case (+ (countleaves (car tree)) (countleaves (cdr tree)))))) (define (leaf? x) (not (pair? x))) Example #1 (countleaves (list 2)) (countleaves ) (countleaves (2)) (+ (countleaves 2) (countleaves nil)) (+ 1 0) ==> 1 2 6.001 SICP
countleaves and substitution model – pg. 2 (define (countleaves tree) (cond ((null? tree) 0) ;base case ((leaf? tree) 1) ;base case (else ;recursive case (+ (countleaves (car tree)) (countleaves (cdr tree)))))) (define (leaf? x) (not (pair? x))) Example #2 (countleaves (list 5 7)) (countleaves ) (countleaves (5 7) ) (+ (countleaves 5) (countleaves (7) )) (+ 1 (+ (countleaves 7) (countleaves nil))) (+ 1 (+ 1 0)) ==> 2 7 5 6.001 SICP
countleaves – bigger example (define my-tree (list 4 (list 5 7) 2)) (countleaves my-tree) (countleaves (4 (5 7) 2) ) (+ (countleaves 4) (countleaves ((5 7) 2) )) ==> 4 4 2 5 7 my-tree (cl (4 (5 7) 2)) + (cl 4) (cl ((5 7) 2) ) 1 + (cl (5 7)) (cl (2)) + (cl 5) (cl (7)) + (cl 2) (cl nil) + (cl 7) (cl nil) 1 1 1
Your Turn: scale-tree Goal: given a tree, produce a new tree with all the leaves scaled Strategy base case: scale of empty tree is empty tree base case: scale of a leaf is product otherwise, recursive strategy: build a new tree from a scaled version of the first child and a scaled version of the rest of children Implementation: (define (scale-tree tree factor) (cond ((null? tree) nil) ;base case ((leaf? tree) (* tree factor)) (else ;recursive case (cons (scale-tree (cdr tree) ))))) (scale-tree (car tree) factor) factor 6.001 SICP
Alternative scale-tree Strategy base case: scale of empty tree is empty tree base case: scale of a leaf is product otherwise: build a new tree from a scaled version of the children recognize that a tree is a list of subtrees and use a list oriented HOP! Alternative Implementation using map: (define (scale-tree tree factor) (cond ((null? tree) nil) ((leaf? tree) (* tree factor)) (else ;it’s a list of subtrees (map (lambda (child) (scale-tree child factor)) tree)))) 6.001 SICP
Pairs, Lists, & Trees Trees user knows trees are also lists Lists user knows lists are also pairs Pairs contract for cons, car, cdr Conventions that enable us to think about lists and trees. Specified the implementations for lists and trees: weak data abstraction How build stronger abstractions? 6.001 SICP
Elements of a Data Abstraction -- Pair Abstaction -- 1. Constructor ;cons: A, B -> Pair<A,B>; A & B = anytype (cons <x> <y>) ==> <p> 2. Accessors (car <p>) ; car: Pair<A,B> -> A (cdr <p>) ; cdr: Pair<A,B> -> B 3. Contract (car (cons <x> <y>)) ==> <x> (cdr (cons <x> <y>)) ==> <y> 4. Operations ; pair?: anytype -> boolean (pair? <p>) 5. Abstraction Barrier Say nothing about implementation! 6. Concrete Representation & Implementation Could have alternative implementations!
Alternative Pair Implementation ;cons: A, B -> Pair<A,B> (define (cons x y) (lambda (m) (if (= m 0) x y))) ; car: Pair<A,B> -> A (define (car p) (p 0)) ; cdr: Pair<A,B> -> B (define (cdr p) (p 1)) Check with Substitution Model (cdr (cons 62 65)) (cdr (lambda (m) (if (= m 0) 62 65))) (cdr [#compound-proc ...]) ([#compound-proc ...] 1) (if (= 1 0) 62 65) 65 6.001 SICP
Rational numbers as an example A rational number is a ratio n/d a/b + c/d = (ad + bc)/bd a/b * c/d = (ac)/(bd) 6.001 SICP
Rational Number Abstraction 1. Constructor ; make-rat: integer, integer -> Rat (make-rat <n> <d>) -> <r> 2. Accessors ; numer, denom: Rat -> integer (numer <r>) (denom <r>) 3. Contract (numer (make-rat <n> <d>)) ==> <n> (denom (make-rat <n> <d>)) ==> <d> 4. Layered Operations (print-rat <r>) prints rat (+rat x y) ; +rat: Rat, Rat -> Rat (*rat x y) ; +rat: Rat, Rat -> Rat 5. Abstraction Barrier Say nothing about implementation! 6.001 SICP
Rational Number Abstraction 1. Constructor 2. Accessors 3. Contract 4. Layered Operations 5. Abstraction Barrier 6. Concrete Representation & Implementation ; Rat = Pair<integer,integer> (define (make-rat n d) (cons n d)) (define (numer r) (car r)) (define (denom r) (cdr r)) 6.001 SICP
Alternative Rational Number Abstraction 1. Constructor 2. Accessors 3. Contract 4. Layered Operations 5. Abstraction Barrier 6. Concrete Representation & Implementation ; Rat = List (define (make-rat n d) (list n d)) (define (numer r) (car r)) (define (denom r) (cadr r)) 6.001 SICP
print-rat Layered Operation ; print-rat: Rat -> undef (define (print-rat rat) (display (numer rat)) (display "/") (display (denom rat))) 6.001 SICP
Layered Rational Number Operations ; +rat: Rat, Rat -> Rat (define (+rat x y) (make-rat (+ (* (numer x) (denom y)) (* (numer y) (denom x))) (* (denom x) (denom y)))) (define (*rat x y) (make-rat (* (numer x) (numer y)) 6.001 SICP
Using our system (define one-half (make-rat 1 2)) (define three-fourths (make-rat 3 4)) (define new (+rat one-half three-fourths)) (numer new) 10 (denom new) 8 Oops – should be 5/4 not 10/8!!\ 6.001 SICP
“Rationalizing” Implementation (define (gcd a b) (if (= b 0) a (gcd b (remainder a b)))) Strategy: remove common factors when access numer and denom (define (numer r) (let ((g (gcd (car r) (cdr r)))) (/ (car r) g))) (define (denom r) (/ (cdr r) g))) (define (make-rat n d) (cons n d)) 6.001 SICP
Alternative “Rationalizing” Implementation Strategy: remove common factors when create a rational number (define (numer r) (car r)) (define (denom r) (cdr r)) (define (make-rat n d) (let ((g (gcd n d))) (cons (/ n g) (/ d g)))) (define (gcd a b) (if (= b 0) a (gcd b (remainder a b)))) 6.001 SICP
Alternative +rat Operations (define (+rat x y) (make-rat (+ (* (numer x) (denom y)) (* (numer y) (denom x))) (* (denom x) (denom y)))) (cons (+ (* (car x) (cdr y)) (* (car y) (cdr x))) (* (cdr x) (cdr y)))) (let ((n (+ (* (car x) (cdr y)) (* (car y) (cdr x)))) (d (* (cdr x) (cdr y)))) (let ((g (gcd n d))) (cons (/ n g) (/ d g))))) 6.001 SICP
Summary Conventional Interfaces: Pairs Lists Trees recursion down multiple paths Data Abstraction constructors accessors contract layered operations ---------- abstraction barrier! ------- implementation Abstraction barrier enables alternative implementations 6.001 SICP
Recitation Problem (for Friday, 2/18/00) Implement a procedure enumerate-leaves that takes a tree, and procedures a (flat) list of all the leaves of the tree. E.g. (enumerate-leaves (list 1 (list 3 4 5) (list 2 30))) ==> (1 3 4 5 2 30) 6.001 SICP