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