今までは手続きの抽象化、ここからはデータの抽象化。
リンク先のサイトの Figure 2.1: Data-abstraction barriers in the rational-number package が分かりやすい。
Programs that use rational numbers
- (Rational numbers in problem domain)
add-rat sub-rat ...
- (Rational numbers as numerators and denominators)
make-rat numer denom
- (Rational numbers as pairs)
cons car cdr
前準備
(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)))) (define (make-rat n d) (let ((g (gcd n d))) (cons (/ n g) (/ d g)))) (define (numer x) (car x)) (define (denom x) (cdr x)) (define (print-rat x) (newline) (display (numer x)) (display "/") (display (denom x)))
2.1
(define (make-rat n d) (define (sign x) (cond ((positive? x) 1) ((negative? x) -1) (else 0))) (let ((g (* (gcd n d) (sign d)))) (cons (/ n g) (/ d g))))
2.2
(define (make-point x y) (cons x y)) (define (x-point p) (car p)) (define (y-point p) (cdr p)) (define (print-point p) (newline) (display "(") (display (x-point p)) (display ",") (display (y-point p)) (display ")")) (define (make-segment s e) (cons s e)) (define (start-segment s) (car s)) (define (end-segment s) (cdr s)) (define (midpoint-segment s) (let ((start (start-segment s)) (end (end-segment s))) (make-point (/ (+ (x-point start) (x-point end)) 2) (/ (+ (y-point start) (y-point end)) 2))))
2.3
(define (make-rect-tb top bottom) (cons top bottom)) (define (top-rect r) (car r)) (define (bottom-rect r) (cdr r)) (define (make-rect-lr left right) (cons left right)) (define (left-rect r) (car r)) (define (right-rect r) (cdr r)) (define (length-segment s) (define (square x) (expt x 2)) (let ((start (start-segment s)) (end (end-segment s))) (sqrt (+ (square (- (x-point start) (x-point end))) (square (- (y-point start) (y-point end))))))) (define (perimeter-rect-lr r) (* (+ (length-segment (left-rect r)) (length-segment (right-rect r))) 2)) (define (perimeter-rect-tb r) (* (+ (length-segment (top-rect r)) (length-segment (bottom-rect r))) 2)) (perimeter-rect-lr (make-rect-lr (make-segment (make-point 1 2) (make-point 4 5)) (make-segment (make-point 10 15) (make-point 3 7))))
2.4 (cons)
(define (%cons x y) (lambda (m) (m x y))) (define (%car z) (z (lambda (x y) x))) (define (%cdr z) (z (lambda (x y) y)))
2.5 (cons)
(define (%cons a b) (* (expt 2 a) (expt 3 b))) (define (pow-of x y) (if (zero? (remainder x y)) (+ 1 (pow-of (/ x y) y)) 0)) (define (%car c) (pow-of c 2)) (define (%cdr c) (pow-of c 3))
2.6 (チャーチ数)
前もやったな。
(define zero (lambda (f) (lambda (x) x))) (define (add-1 n) (lambda (f) (lambda (x) (f ((n f) x))))) ; (add-1 zero) ; => (lambda (f) (lambda (x) (f (((lambda (f) (lambda (x) x)) f) x)))) ; => (lambda (f) (lambda (x) (f ( (lambda (x) x) x)))) ; => (lambda (f) (lambda (x) (f x ))) (define one (lambda (f) (lambda (x) (f x)))) ; (add-1 one) ; => (lambda (f) (lambda (x) (f (((lambda (f) (lambda (x) (f x))) f) x)))) ; => (lambda (f) (lambda (x) (f ( (lambda (x) (f x)) x)))) ; => (lambda (f) (lambda (x) (f (f x) ))) (define two (lambda (f) (lambda (x) (f (f x))))) (define (to-number n) ((n (lambda (x) (+ x 1))) 0)) (define (add n m) (lambda (f) (lambda (x) ((m f) ((n f) x))))) (define (mul n m) (lambda (f) (n (m f))))
2.1.4 Extended Exercise: Interval Arithmetic 前準備
区間演算。
(define (add-interval x y) (make-interval (+ (lower-bound x) (lower-bound y)) (+ (upper-bound x) (upper-bound y)))) (define (mul-interval x y) (let ((p1 (* (lower-bound x) (lower-bound y))) (p2 (* (lower-bound x) (upper-bound y))) (p3 (* (upper-bound x) (lower-bound y))) (p4 (* (upper-bound x) (upper-bound y)))) (make-interval (min p1 p2 p3 p4) (max p1 p2 p3 p4)))) (define (div-interval x y) (mul-interval x (make-interval (/ 1.0 (upper-bound y)) (/ 1.0 (lower-bound y)))))
2.7
(define (make-interval l u) (cons l u)) (define (lower-bound i) (car i)) (define (upper-bound i) (cdr i))
2.8
(define (sub-interval x y) (make-interval (- (lower-bound x) (lower-bound y)) (- (upper-bound x) (upper-bound y))))
2.9
(define (width-interval i) (/ (- (upper-bound i) (lower-bound i)) 2))
2.10
(define (div-interval x y) (if (and (not (positive? (lower-bound y))) (not (negative? (upper-bound y)))) (error "div-interval: y spans zero") (mul-interval x (make-interval (/ 1.0 (upper-bound y)) (/ 1.0 (lower-bound y))))))
2.11
(define (mul-interval x y) (if (and (not (positive? (lower-bound x))) (not (negative? (upper-bound x))) (not (positive? (lower-bound y))) (not (negative? (upper-bound y)))) (let ((p1 (* (lower-bound x) (lower-bound y))) (p2 (* (lower-bound x) (upper-bound y))) (p3 (* (upper-bound x) (lower-bound y))) (p4 (* (upper-bound x) (upper-bound y)))) (make-interval (min p1 p2 p3 p4) (max p1 p2 p3 p4))) (let ((p1 (* (lower-bound x) (lower-bound y))) (p2 (* (upper-bound x) (upper-bound y)))) (make-interval (min p1 p2) (max p1 p2))) ))
自信なし。
2.12
(define (make-center-width c w) (make-interval (- c w) (+ c w))) (define (center i) (/ (+ (lower-bound i) (upper-bound i)) 2)) (define (width i) (/ (- (upper-bound i) (lower-bound i)) 2))
(define (make-center-percent c p) (make-center-width c (* c p 0.01))) (define (percent i) (* (/ (width i) (center i)) 100))
2.13 - 2.16
桁落ちとかそういうことかな。数学的な話。省略