ArsDigita University, Structure and Interpretation of Computer Programs

Lecture Notes for Lecture 5 -- 5 October 2000

Topics covered in today's lecture:

Data Abstraction

Arithmetic with Rational Numbers

n1/d1 + n2/d2 = (n1*d2 + n2*d1) / (d1*d2)

n1/d1 - n2/d2 = (n1*d2 - n2*d1) / (d1*d2)

n1/d1 * n2/d2 = (n1*n2) / (d1*d2)

(n1/d1) / (n2/d2) = (n1*d2) / (d1*n2)

n1/d1 = n2/d2 iff n1*d2 = n2*d1

Assume that we have a constructor called make-rat, which takes a numerator and a denominator and returns a rational number representation. Also assume that we have two selectors, numer and denom. Both selectors take a rational number representation. numer returns the numerator of the rational number and denom returns the denominator of the rational number.

(define (add-rat x y)
   (make-rat (+ (* (numer x) (denom y))
                (* (numer y) (denom x)))
             (* (denom x) (denom y))))

(define (sub-rat x y)
   (make-rat (- (* (numer x) (denom y))
                (* (numer y) (denom x)))
             (* (denom x) (denom y))))

(define (mul-rat x y)
   (make-rat (* (numer x) (numer y))
             (* (denom x) (denom y))))

(define (div-rat x y)
   (make-rat (* (numer x) (denom y))
             (* (denom x) (numer y))))

(define (equal-rat? x y)
   (= (* (numer x) (denom y))
      (* (numer y) (denom x))))
We could also write sub-rat by writing negate-rat then using it and add-rat to define sub-rat:
(define (negate-rat x)
   (make-rat (- (numer x))
             (denom x)))

(define (sub-rat x y)
   (add-rat x (negate-rat y)))
How can we write the constructors and selectors? Scheme has a compound structure called a pair which is constructed with the primitive procedure cons. cons takes two arguments and returns a compound data object containing the two arguments as parts.
(define a (cons 2 3)
We can draw box and pointer diagrams to represent cons cells. A cons cell is drawn as two connected squares. For the example above, the first square would have an arrow pointing to the number 2 and the second box would have an arrow pointing to the number 3. See the book or the videotaped lecture to see what they look like.

How do we get the elements from a pair? The first box of the cons cell is called the car. We would write (car a), which would return the number 2. The second box of the cons cell is called the cdr. We would write (cdr a), which would return the number 3.

Cons pairs have the property of closure. Anything constructed by cons can be used as an input element to cons. For example,

(define b (cons 7 8))

(define c (cons b 9))
How can we extract 7 from these pairs? (car b) or (car (car c)). We can also write (car (car c)) as (caar c).

How can we get 8 from these pairs? (cdr b) or (cdr (car c)) (which can also be written as (cdar c)).

Finally, how can we get 9? (cdr c)

Now that we know about cons, car and cdr, let's write make-rat, numer and denom.

(define (make-rat n d) 
   (cons n d))

(define (numer x)
   (car x))

(define (denom x) 
   (cdr x))
These could also be written as follows:
(define make-rat cons)

(define numer car)

(define denom cdr)
And how can we display a rational number?
(define (print-rat x)
   (newline)
   (display (numer x))
   (display "/")
   (display (denom x)))
We're not reducing the rational numbers to the lowest terms. How could we do this? By changing make-rat:
(define (make-rat n d)
   (let ((g (gcd n d)))
      (cons (/ n g) (/ d g))))
We could also implement make-rat as a procedure:
(define (make-rat n d)
   (lambda (proc) (proc n d)))

(define (numer x)
   (x (lambda (a b) a)))

(define (denom x)
   (y (lambda (a b) b)))



Last update: October 2000