(define (make-polar-point r theta) ...)
(define (polar-point? pt) ...)
(define (make-cartesian-point x y) ...)
(define (cartesian-point? pt) ...)
; answer the distance between two
cartesian points
; type: CartesianPoint,CartesianPoint -> number
(define (cart-distance CartPt1 CartPt2) ...)
; convert coordinates
; type: PolarPoint -> CartesianPoint
(define (polar2cartesian PolarPt) ...)
Assume that none of the above functions have internal tag checks.
Use good defensive programming techniques to implement the function
; Point = PolarPoint | CartesianPoint
; type: Point, Point -> number
(define (point-distance pt1 pt2) ...)
(define (point-distance p1 p2)
(cart-distance (cart-if-needed p1) (cart-if-needed p2)))
Clients and implementors
-- client: uses the abstract type (ie, writes code that calls its operations)
-- implementor: builds the abstract type (ie, writes the code of the
operations)
-- contract between them called the spec
Representation choices
-- same abstract type can be represented many ways
-- eg, set as list, tree, vector
Rep independence
-- client need not know how type is represented
-- in fact, client SHOULD not know
Why rep independence?
-- client code neater and simpler
-- no need to change client when rep changes
-- implementor can make type very efficient
Using set:
(define s (insert empty-set 'a))Obvious rep
(define t (insert empty-set 'b))
(define u (union s t))
(define v (difference u t))
(is-member s 'a)
> #f
(is-member s 'b)
> #t
(is-member v 'a)
> #tLook Ma! No rep!
Sample operation:
(define insert cons)What's wrong with this?
(define is-member member)
Tagging code
(define set-tag 'set)Types(define (list2set r)
(cons set-tag r))(define (set2list r)
(if (and (pair? r)
(equal? (car r) set-tag))
(cdr r)
(error "not a set")))
Sample operation
(define (delete set elt)Exercises:
(list2set (remove elt (set2list set))))
Inside and outside
-- Which ops access the rep?
-- the ones that call set2list
-- Sym diff is outside, the rest are inside
Why inside? Why outside?
(define (accumulate f base p)
(cond
((null? p) base)
(else (f (car p) (accumulate f base
(cdr p))))))
(define (remove e p)
(cond ((null? p) '())
((equal? e (car
p))(cdr p))
(else (cons
(car p)
(remove e (cdr p))))))
(define set-tag 'set)
(define (list2set r)
(cons set-tag r))
(define (set2list r)
(if (and (pair? r)
(equal?
(car r) set-tag))
(cdr r)
(error "not a set")))
(define empty-set (list2set null))
(define (is-member set elt)
(pair? (member elt (set2list set))))
(define (insert set elt)
(if (is-member set elt)
set
(list2set
(cons elt (set2list set)))))
(define (delete set elt)
(list2set (remove elt (set2list set))))
(define (union s1 s2)
(accumulate
(lambda (elt s) (insert s elt))
s1 (set2list s2)))
(define (difference s1 s2)
(accumulate
(lambda (elt s) (delete s elt))
s1 (set2list s2)))
(define (sym-diff s1 s2)
(union (difference s1 s2)
(difference s2 s1)))
(define s (insert empty-set 'a))
(define t (insert empty-set 'b))
(define u (union s t))
(define v (difference u t))