Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #lang racket
- ;;; op table
- (define op-table (make-hash))
- (define (put op type item)
- (hash-set! op-table (list op type) item))
- (define (get op type)
- (hash-ref op-table (list op type)))
- ;; I'm going to use lists instead of dotted pairs.
- ;;; generic operations
- (define (attach-tag type-tag contents)
- (list type-tag contents))
- (define (type-tag datum)
- (if (list? datum)
- (first datum)
- (error "bad tagged datum -- TYPE-TAG" datum)))
- (define (contents datum)
- (if (list? datum)
- (second datum)
- (error "bad tagged datum -- CONTENTS" datum)))
- (define (apply-generic op . args)
- (define type-tags (map type-tag args))
- (define proc (get op type-tags))
- (if proc
- (apply proc (map contents args))
- (error "no method for these types -- APPLY-GENERIC"
- (list op type-tags))))
- (define (add x y) (apply-generic 'add x y))
- (define (sub x y) (apply-generic 'sub x y))
- (define (mul x y) (apply-generic 'mul x y))
- (define (div x y) (apply-generic 'div x y))
- (define (equ? x y) (apply-generic 'equ x y))
- (define (=zero? x) (apply-generic '=zero x))
- (define (re-part z) (apply-generic 're-part z))
- (define (im-part z) (apply-generic 'im-part z))
- (define (mag-part z) (apply-generic 'mag-part z))
- (define (ang-part z) (apply-generic 'ang-part z))
- ;;; constructors
- (define (make-scheme-number n)
- ((get 'make 'scheme-number) n))
- (define (make-rational n d)
- ((get 'make 'rational) n d))
- (define (make-complex-from-real-imag x y)
- ((get 'make-from-real-imag 'complex) x y))
- (define (make-complex-from-mag-ang r a)
- ((get 'make-from-mag-ang 'complex) r a))
- ;;; scheme numbers
- (define (install-scheme-number-package)
- (define (tag x)
- (attach-tag 'scheme-number x))
- (put 'add '(scheme-number scheme-number)
- (lambda (x y) (tag (+ x y))))
- (put 'sub '(scheme-number scheme-number)
- (lambda (x y) (tag (- x y))))
- (put 'mul '(scheme-number scheme-number)
- (lambda (x y) (tag (* x y))))
- (put 'div '(scheme-number scheme-number)
- (lambda (x y) (tag (/ x y))))
- (put 'make 'scheme-number
- (lambda (x) (tag x)))
- (put 'equ '(scheme-number scheme-number)
- =)
- (put '=zero '(scheme-number)
- zero?)
- 'done)
- (install-scheme-number-package)
- ;;; rational numbers
- (define (install-rational-package)
- ;; internal procedures
- (define (numer x) (first x))
- (define (denom x) (second x))
- (define (make-rat n d)
- (let ((g (gcd n d)))
- (list (/ n g) (/ d g))))
- (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 (equ? x y)
- (= (* (numer x) (denom y))
- (* (denom x) (numer y))))
- (define (=zero? x) (= (numer x) 0))
- ;; interface to the rest of the system
- (define (tag x) (attach-tag 'rational x))
- (put 'equ '(rational rational)
- (lambda (x y) (equ? x y)))
- (put '=zero '(rational)
- (lambda (x) (=zero? x)))
- (put 'add '(rational rational)
- (lambda (x y) (tag (add-rat x y))))
- (put 'sub '(rational rational)
- (lambda (x y) (tag (sub-rat x y))))
- (put 'mul '(rational rational)
- (lambda (x y) (tag (mul-rat x y))))
- (put 'div '(rational rational)
- (lambda (x y) (tag (div-rat x y))))
- (put 'make 'rational
- (lambda (n d) (tag (make-rat n d))))
- 'done)
- (install-rational-package)
- ;;; complex rectangular numbers
- (define (install-rectangular-package)
- ;; internal procedures
- (define (re-part z) (first z))
- (define (im-part z) (second z))
- (define (make-from-real-imag x y) (list x y))
- (define (mag-part z)
- (sqrt (+ (sqr (re-part z))
- (sqr (im-part z)))))
- (define (ang-part z)
- (atan (im-part z) (re-part z)))
- (define (make-from-mag-ang r a)
- (list (* r (cos a)) (* r (sin a))))
- ;; interface to the rest of the system
- (define (tag x) (attach-tag 'rectangular x))
- (put 're-part '(rectangular) re-part)
- (put 'im-part '(rectangular) im-part)
- (put 'mag-part '(rectangular) mag-part)
- (put 'ang-part '(rectangular) ang-part)
- (put 'make-from-real-imag 'rectangular
- (lambda (x y) (tag (make-from-real-imag x y))))
- (put 'make-from-mag-ang 'rectangular
- (lambda (r a) (tag (make-from-mag-ang r a))))
- 'done)
- (install-rectangular-package)
- ;;; complex polar numbers
- (define (install-polar-package)
- ;; internal procedures
- (define (mag-part z) (first z))
- (define (ang-part z) (second z))
- (define (make-from-mag-ang r a) (list r a))
- (define (re-part z)
- (* (mag-part z) (cos (ang-part z))))
- (define (im-part z)
- (* (mag-part z) (sin (ang-part z))))
- (define (make-from-real-imag x y)
- (list (sqrt (+ (sqr x) (sqr y)))
- (atan y x)))
- ;; interface to the rest of the system
- (define (tag x) (attach-tag 'polar x))
- (put 're-part '(polar) re-part)
- (put 'im-part '(polar) im-part)
- (put 'mag-part '(polar) mag-part)
- (put 'ang-part '(polar) ang-part)
- (put 'make-from-real-imag 'polar
- (lambda (x y) (tag (make-from-real-imag x y))))
- (put 'make-from-mag-ang 'polar
- (lambda (r a) (tag (make-from-mag-ang r a))))
- 'done)
- (install-polar-package)
- ;;; generic complex numbers
- (define (install-complex-package)
- ;; imported procedures from rectangular and polar packages
- (define (make-from-real-imag x y)
- ((get 'make-from-real-imag 'rectangular) x y))
- (define (make-from-mag-ang r a)
- ((get 'make-from-mag-ang 'polar) r a))
- ;; internal procedures
- (define (add-complex z1 z2)
- (make-from-real-imag (+ (re-part z1) (re-part z2))
- (+ (im-part z1) (im-part z2))))
- (define (sub-complex z1 z2)
- (make-from-real-imag (- (re-part z1) (re-part z2))
- (- (im-part z1) (im-part z2))))
- (define (mul-complex z1 z2)
- (make-from-mag-ang (* (mag-part z1) (mag-part z2))
- (+ (ang-part z1) (ang-part z2))))
- (define (div-complex z1 z2)
- (make-from-mag-ang (/ (mag-part z1) (mag-part z2))
- (- (ang-part z1) (ang-part z2))))
- (define (equ? z1 z2)
- ; account for round-off error
- (and
- (< (abs (- (re-part z1) (re-part z2))) 0.0001)
- (< (abs (- (im-part z1) (im-part z2))) 0.0001)))
- (define (=zero? z)
- (or (= (mag-part z) 0)
- ; account for round-off error
- (and (< (abs (re-part z)) 0.0001)
- (< (abs (im-part z)) 0.0001))))
- ;; interface to the rest of the system
- (put 're-part '(complex) re-part)
- (put 'im-part '(complex) im-part)
- (put 'mag-part '(complex) mag-part)
- (put 'ang-part '(complex) ang-part)
- (define (tag z) (attach-tag 'complex z))
- (put 'equ '(complex complex)
- (lambda (z1 z2) (equ? z1 z2)))
- (put '=zero '(complex)
- (lambda (z) (=zero? z)))
- (put 'add '(complex complex)
- (lambda (z1 z2) (tag (add-complex z1 z2))))
- (put 'sub '(complex complex)
- (lambda (z1 z2) (tag (sub-complex z1 z2))))
- (put 'mul '(complex complex)
- (lambda (z1 z2) (tag (mul-complex z1 z2))))
- (put 'div '(complex complex)
- (lambda (z1 z2) (tag (div-complex z1 z2))))
- (put 'make-from-real-imag 'complex
- (lambda (x y) (tag (make-from-real-imag x y))))
- (put 'make-from-mag-ang 'complex
- (lambda (r a) (tag (make-from-mag-ang r a))))
- 'done)
- (install-complex-package)
- (define q1 (make-rational 1 2))
- (define q2 (make-rational 3 4))
- (add q1 q2)
- ;; '(rational (5 4))
- (sub q1 q2)
- ;; '(rational (-1 4))
- (mul q1 q2)
- ;; '(rational (3 8))
- (div q1 q2)
- ;; '(rational (2 3))
- (define z1 (make-complex-from-real-imag 3 4))
- (define z2 (make-complex-from-mag-ang 1 pi))
- (add z1 z2)
- ;; '(complex (rectangular (2.0 4.0)))
- (sub z1 z2)
- ;; '(complex (rectangular (4.0 4.0)))
- (mul z1 z2)
- ;; '(complex (polar (5 4.068887871591405)))
- (div z1 z2)
- ;; '(complex (polar (5 -2.214297435588181)))
- ;;;;;;;;;;
- ;; 2.77 ;;
- ;;;;;;;;;;
- ;; I'm using mag-part for magnitude so as not to conflict with the built-in racket
- ;; magnitude function. To be consistent I'll also use ang-part instead of angle.
- (define z '(complex (rectangular (3 4))))
- ;; without the added lines
- ;; (mag-part z)
- ;; ;; hash-ref: no value found for key
- ;; ;; key: '(mag-part (complex))
- ;; with the added lines
- (mag-part z)
- ;; 5
- ;; In evaluating (mag-part z), apply-generic is called twice. The first call
- ;; strips off the 'complex tag and dispatches to the generic mag-part again. This
- ;; is because of the lines we added to the complex package. The second call
- ;; strips off the 'rectangular tag and dispatches the mag-part procedure defined
- ;; in the rectangular package.
- ;; the manual trace
- ;; recall that (apply-generic op . args)
- ;; is (apply proc (map contents args))
- ;; where proc is (get op (map type-tag args))
- ;; (mag-part z)
- ;; (mag-part '(complex (rectangular (3 4))))
- ;; (apply-generic 'mag-part '(complex (rectangular (3 4))))
- ;; ;; this first call to apply-generic strips off the 'complex tag
- ;; (apply (get 'mag-part 'complex) '(rectangular (3 4)))
- ;; ;; the lines we added to the complex package say to use
- ;; ;; the generic mag-part again for (get 'mag-part 'complex)
- ;; (mag-part '(rectangular (3 4)))
- ;; (apply-generic 'mag-part '(rectangular (3 4)))
- ;; ;; this second call to apply-generic strips off the 'rectangular tag
- ;; ;; and uses the mag-part function defined in the complex rectangular package
- ;; (apply (get 'mag-part 'rectangular) '(3 4))
- ;; (apply (lambda (z) (sqrt (+ (sqr (re-part z)) (sqr (im-part z))))) '(3 4))
- ;; (sqrt (+ (sqr 3) (sqr 4)))
- ;; 5
- ;;;;;;;;;;
- ;; 2.78 ;;
- ;;;;;;;;;;
- ;; (define (attach-tag type-tag contents)
- ;; (if (number? contents)
- ;; contents
- ;; (list type-tag contents)))
- ;; (define (type-tag datum)
- ;; (cond [(number? datum) 'scheme-number]
- ;; [(list? datum) (first datum)]
- ;; [else (error "bad tagged datum -- TYPE-TAG" datum)]))
- ;; (define (contents datum)
- ;; (cond [(number? datum) datum]
- ;; [(list? datum) (second datum)]
- ;; [else (error "bad tagged datum -- CONTENTS" datum)]))
- ;;;;;;;;;;
- ;; 2.79 ;;
- ;;;;;;;;;;
- ;; Here is the code that was added above to implement equ?:
- ;; (define (equ? x y) (apply-generic 'equ x y))
- ;; ;; inside the scheme number package
- ;; (put 'equ '(scheme-number scheme-number)
- ;; =)
- ;; ;; inside the rational number package
- ;; (define (equ? x y)
- ;; (= (* (numer x) (denom y))
- ;; (* (denom x) (numer y))))
- ;; (put 'equ '(rational rational)
- ;; (lambda (x y) (equ? x y)))
- ;; ;; inside the generic complex number package
- ;; (define (equ? z1 z2)
- ;; ; account for round-off error
- ;; (and
- ;; (< (abs (- (re-part z1) (re-part z2))) 0.0001)
- ;; (< (abs (- (im-part z1) (im-part z2))) 0.0001)))
- ;; (put 'equ '(complex complex)
- ;; (lambda (z1 z2) (equ? z1 z2)))
- (equ? (make-scheme-number 1)
- (make-scheme-number 1))
- ;; #t
- (equ? (make-scheme-number 2)
- (make-scheme-number 3))
- ;; #f
- (equ? (make-rational 1 2) (make-rational 3 6))
- ;; #t
- (equ? (make-rational 1 2) (make-rational 2 3))
- ;; #f
- (equ? (make-complex-from-real-imag -1 0)
- (make-complex-from-mag-ang 1 pi))
- ;; #t
- (equ? (make-complex-from-real-imag 3 4)
- (make-complex-from-mag-ang 3 4))
- ;; #f
- ;;;;;;;;;;
- ;; 2.80 ;;
- ;;;;;;;;;;
- ;; Here is the code that was added above to implement =zero?:
- ;; (define (=zero? x) (apply-generic '=zero x))
- ;; ;; inside the scheme number package
- ;; (put '=zero '(scheme-number)
- ;; zero?)
- ;; ;; inside the rational number package
- ;; (define (=zero? x) (= (numer x) 0))
- ;; (put '=zero '(rational)
- ;; (lambda (x) (=zero? x)))
- ;; ;; inside the generic complex numbers package
- ;; (define (=zero? z)
- ;; (or (= (mag-part z) 0)
- ;; ; account for round-off error
- ;; (and (< (abs (re-part z)) 0.0001)
- ;; (< (abs (im-part z)) 0.0001))))
- ;; (put '=zero '(complex)
- ;; (lambda (z) (=zero? z)))
- (=zero? (make-scheme-number 0))
- ;; #t
- (=zero? (make-scheme-number 2))
- ;; #f
- (=zero? (sub (make-rational 1 2)
- (make-rational 5 10)))
- ;; #t
- (=zero? (sub (make-complex-from-real-imag 1 0)
- (make-complex-from-mag-ang 1 pi)))
- ;; #f
- (=zero? (sub (make-complex-from-real-imag -1 0)
- (make-complex-from-mag-ang 1 pi)))
- ;; #t
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement