Data Abstraction

Abstraction barriers: programs using rationals → operations (add-rat) → constructors/selectors (make-rat, numer) → representation (pairs). Changing the representation only affects the bottom layer.

;; Rational numbers with an abstraction barrier (SICP 2.1)
;; Constructor and selectors: the ONLY procedures that know the representation
(define (make-rat n d)
  (if (= d 0) (error "Zero denominator" n))
  (let ((g (gcd n d))
        (sign (if (< d 0) -1 1)))
    (cons (* sign (/ n g)) (* sign (/ d g)))))
(define (numer x) (car x))
(define (denom x) (cdr x))

;; Operations use only the constructor and selectors
(define (add-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 (equal-rat? x y)
  (= (* (numer x) (denom y)) (* (numer y) (denom x))))
(define (print-rat x)
  (display (numer x)) (display "/") (display (denom x)) (newline))

(print-rat (add-rat (make-rat 1 2) (make-rat 1 3)))   ; 5/6

;; What IS data? Pairs implemented with nothing but procedures (SICP 2.1.3)
(define (my-cons x y) (lambda (m) (m x y)))
(define (my-car z) (z (lambda (p q) p)))
(define (my-cdr z) (z (lambda (p q) q)))
(my-car (my-cons 1 2))          ; 1