;;; Rational arithmetic ;;; n1 n2 n1 d2 + n2 d1 ;;; -- + -- = ------------- ;;; d1 d2 d1 d2 ;;; n1 n2 n1 d2 - n2 d1 ;;; -- - -- = ------------- ;;; d1 d2 d1 d2 ;;; n1 n2 n1 n2 ;;; -- * -- = ----- ;;; d1 d2 d1 d2 ;;; n1 n2 n1 d2 ;;; -- / -- = ----- ;;; d1 d2 d1 n2 ;;; n1 n2 ;;; -- = -- <==> n1 d2 = n2 d1 ;;; d1 d2 ;;; Wishful thinking (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)))) ;;; An Implementation (define (make-rat x y) (lambda (m) (cond ((= m 0) x) ((= m 1) y) (else (error "Huh?"))))) (define (numer x) (x 0)) (define (denom x) (x 1)) #| (define one-sixth (make-rat 1 6)) ;Value: one-sixth (numer one-sixth) ;Value: 1 (denom one-sixth) ;Value: 6 (define one-third (make-rat 1 3)) ;Value: one-third (define x (add-rat one-sixth one-third)) ;Value: x (numer x) ;Value: 9 (denom x) ;Value: 18 |# ;;; Another Implementation (define (make-rat x y) (let ((d (gcd x y))) (let ((u (quotient x d)) (v (quotient y d))) (lambda (m) (cond ((= m 0) u) ((= m 1) v) (else (error "Huh?"))))))) (define (numer x) (x 0)) (define (denom x) (x 1)) ;;; Yet another Implementation (define (make-rat x y) (let ((d (gcd x y))) (lambda (m) (let ((u (quotient x d)) (v (quotient y d))) (cond ((= m 0) u) ((= m 1) v) (else (error "Huh?"))))))) (define (numer x) (x 0)) (define (denom x) (x 1)) ;;; And yet another Implementation (define (make-rat x y) (lambda (m) (let ((d (gcd x y))) (let ((u (quotient x d)) (v (quotient y d))) (cond ((= m 0) u) ((= m 1) v) (else (error "Huh?"))))))) (define (numer x) (x 0)) (define (denom x) (x 1)) ;;; Abstracting out the pairing ;;; The contract ;;; Forall A, B ;;; (car (cons A B)) = A ;;; and ;;; (cdr (cons A B)) = B #| ;;; Could have been implemented (define (cons a b) (lambda (m) (cond ((= m 0) a) ((= m 1) b) (else (error "Huh?"))))) (define (car x) (x 0)) (define (cdr x) (x 1)) |# ;;; Actually not this way ... ;;; But none of our business! ;;; Implementation #1 with pairs (define (make-rat x y) (let ((d (gcd x y))) (let ((u (quotient x d)) (v (quotient y d))) (cons u v)))) (define (numer x) (car x)) (define (denom x) (cdr x)) ;;; Implementation #2 with pairs (define (make-rat x y) (cons x y)))) (define (numer x) (let ((d (gcd (car x) (cdr x)))) (quotient (car x) d))) (define (denom x) (let ((d (gcd (car x) (cdr x)))) (quotient (cdr x) d))) ;;; A better contract for pairs ;;; Forall A, B ;;; (car (cons A B)) = A ;;; and ;;; (cdr (cons A B)) = B ;;; and ;;; (pair? (cons A B)) = #t ;;; and if (number? A) = #t ;;; then (pair? A) = #f ;;; There is a special useful ;;; pattern of pairs, called ;;; lists. ;;; There is a distinguished ;;; object, the empty list. ;;; It is written '(). ;;; It is not a pair. ;;; It is the only object ;;; satisfying the predicate ;;; null? ;;; A list is a chain of pairs, ;;; the cdr of each is the next, ;;; ending in the empty list. ;;; The following constructs a ;;; list of 4 elements. #| (cons 1 (cons 2 (cons 3 (cons 4 '())))) ;;; It prints as (1 2 3 4) ;;; LIST provides a shortcut ;;; for making chains of pairs. (list 1 2 3 4) ==> (1 2 3 4) (car (list 1 2 3 4)) ==> 1 (cdr (list 1 2 3 4)) ==> (2 3 4) (car (cdr (list 1 2 3 4))) ==> 2 (cadr (list 1 2 3 4)) ==> 2 |# (define 3d-vector list) (define x-coord car) (define y-coord cadr) (define z-coord caddr) (define (vector+vector v1 v2) (3d-vector (+ (x-coord v1) (x-coord v2)) (+ (y-coord v1) (y-coord v2)) (+ (z-coord v1) (z-coord v2)))) (define (scalar*vector a v) (3d-vector (* a (x-coord v)) (* a (y-coord v)) (* a (z-coord v)))) ;;; ... ;;; Alonzo Church's implementation ;;; of CONS needs almost nothing! #| (define cons (lambda (a d) (lambda (m) (m a d)))) (define car (lambda (x) (x (lambda (a d) a)))) (define cdr (lambda (x) (x (lambda (a d) d)))) |# #| (car (cons U V)) ((lambda (x) (x (lambda (a d) a))) (cons U V)) ((lambda (x) (x (lambda (a d) a))) ((lambda (a d) (lambda (m) (m a d))) U V)) ((lambda (x) (x (lambda (a d) a))) (lambda (m) (m U V))) ((lambda (m) (m U V)) (lambda (a d) a)) ((lambda (a d) a) U V) U |#