Advertisement
Guest User

Untitled

a guest
Aug 8th, 2010
55
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scheme 13.34 KB | None | 0 0
  1. #lang planet neil/sicp
  2.  
  3. ;; Ex 2.83
  4. ;;
  5. ;; NB These procedures won't work because apply-generic is still the
  6. ;; version that uses generalised coercion which hasn't been implemented.
  7. ;; This version is using a raise strategy.
  8. (define (apply-generic op . args)
  9.  
  10.   (define (all-coercable? coerce-procs)
  11.     (not (member #f coerce-procs)))
  12.  
  13.   (define (coerce-args coercion-procs args)
  14.     (map (lambda (coerce-proc arg)
  15.            (coerce-proc arg))
  16.          coercion-procs
  17.          args))
  18.  
  19.   ; attempt to coerce all args into a common type among the args
  20.   (define (apply-with-coercion arg-types)
  21.    
  22.     ; attempt to coerce all args using each tag-type in turn
  23.     ; it's a scoped procedure to keep the original arguments (arg-types) for error reporting
  24.     (define (coerce-types tags)
  25.       (if (null? tags)   ; all targets exhausted
  26.           (error "No method for these types - APPLY-GENERIC"
  27.                  (list op arg-types))
  28.           (let* ((target-type (car tags))
  29.                  (arg-coercions (map        ; get all the coercion procedures from the target
  30.                                  (lambda (coerce-from)
  31.                                    (if (eq? coerce-from target-type)
  32.                                        identity
  33.                                        (get-coercion coerce-from target-type)))
  34.                                  arg-types)))
  35.             (if (all-coercable? arg-coercions)
  36.                 ; the target type is valid if all the args can be coerced
  37.                 (apply apply-generic  
  38.                        op
  39.                        (coerce-args arg-coercions args))
  40.                 ; target-type is not valid, so try the next one in the list
  41.                 (coerce-types (cdr tags))))))        ; try the next target type
  42.    
  43.     (coerce-types arg-types))
  44.  
  45.   (let* ((type-tags (map type-tag args))
  46.          (proc (get op type-tags)))
  47.     (if proc
  48.         (apply proc (map contents args))
  49.         (apply-with-coercion type-tags))))
  50.  
  51.  
  52.  
  53. ;;
  54. ;; ======================================================================
  55. ;;
  56. ;; To test the exercises I need an implementation of put and get.
  57. ;; These are taken directly from section 3.3.3 of the book
  58. ;; http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-22.html#%_sec_3.3.3
  59. ;;
  60. ;; ======================================================================
  61. (define (make-table)
  62.   (let ((local-table (list '*table*)))
  63.     (define (lookup key-1 key-2)
  64.       (let ((subtable (assoc key-1 (cdr local-table))))
  65.         (if subtable
  66.             (let ((record (assoc key-2 (cdr subtable))))
  67.               (if record
  68.                   (cdr record)
  69.                   false))
  70.             false)))
  71.     (define (insert! key-1 key-2 value)
  72.       (let ((subtable (assoc key-1 (cdr local-table))))
  73.         (if subtable
  74.             (let ((record (assoc key-2 (cdr subtable))))
  75.               (if record
  76.                   (set-cdr! record value)
  77.                   (set-cdr! subtable
  78.                             (cons (cons key-2 value)
  79.                                   (cdr subtable)))))
  80.             (set-cdr! local-table
  81.                       (cons (list key-1
  82.                                   (cons key-2 value))
  83.                             (cdr local-table)))))
  84.       'ok)    
  85.     (define (dispatch m)
  86.       (cond ((eq? m 'lookup-proc) lookup)
  87.             ((eq? m 'insert-proc!) insert!)
  88.             ((eq? m 'table) local-table)
  89.             (else (error "Unknown operation -- TABLE" m))))
  90.     dispatch))
  91.  
  92. (define operation-table (make-table))
  93. (define get (operation-table 'lookup-proc))
  94. (define put (operation-table 'insert-proc!))
  95.  
  96. (define coercion-table (make-table))
  97. (define get-coercion (coercion-table 'lookup-proc))
  98. (define put-coercion (coercion-table 'insert-proc!))
  99.  
  100. (define (square x) (* x x))
  101.  
  102. (define (attach-tag type-tag contents)
  103.   (if (eq? type-tag 'scheme-number)
  104.       contents
  105.       (cons type-tag contents)))
  106.  
  107. (define (type-tag datum)
  108.   (cond ((pair? datum) (car datum))
  109.         ((number? datum) 'scheme-number)
  110.         (else (error "Bad tagged datum -- TYPE-TAG" datum))))
  111.  
  112. (define (contents datum)
  113.   (cond ((pair? datum) (cdr datum))
  114.         ((number? datum) cdr datum)
  115.         (else (error "Bad tagged datum -- CONTENTS" datum))))
  116.  
  117.  
  118. ;; ======================================================================
  119. ;;
  120. ;; The integer number package
  121. ;;
  122. ;; ======================================================================
  123. (define (install-integer-package)
  124.   ;; internal procedures
  125.   (define (tag x) (attach-tag 'integer x))    
  126.  
  127.   ;; interface to rest of the system
  128.   (put 'add    '(integer integer) (lambda (x y) (tag (+ x y))))
  129.   (put 'sub    '(integer integer) (lambda (x y) (tag (- x y))))
  130.   (put 'mul    '(integer integer) (lambda (x y) (tag (* x y))))
  131.   (put 'div    '(integer integer) (lambda (x y) (tag (/ x y))))
  132.   (put 'equ?   '(integer integer) =)
  133.   (put '=zero? '(integer integer) zero?)
  134.   (put 'raise  '(integer) (lambda (n) (make-rational n 1)))
  135.   (put 'make   'integer (lambda (n) (tag n)))
  136.   'done)
  137.  
  138.  
  139. ;; ======================================================================
  140. ;;
  141. ;; The rational number package
  142. ;;
  143. ;; ======================================================================
  144. (define (install-rational-package)
  145.   ;; internal procedures
  146.   (define (numer x) (car x))
  147.   (define (denom x) (cdr x))
  148.   (define (make-rat n d) (let ((g (gcd n d)))
  149.                            (cons (/ n g) (/ d g))))
  150.   (define (add-rat x y) (make-rat (+ (* (numer x) (denom y))
  151.                                      (* (numer y) (denom x)))
  152.                                   (* (denom x) (denom y))))
  153.   (define (sub-rat x y) (make-rat (- (* (numer x) (denom y))
  154.                                      (* (numer y) (denom x)))
  155.                                   (* (denom x) (denom y))))
  156.   (define (mul-rat x y) (make-rat (* (numer x) (numer y))
  157.                                   (* (denom x) (denom y))))
  158.   (define (div-rat x y) (make-rat (* (numer x) (denom y))
  159.                                   (* (denom x) (numer y))))
  160.   (define (equ-rat x y) (and (equ? (numer x) (numer y))
  161.                              (equ? (denom x) (denom y))))
  162.   (define (=zero-rat x) (zero? (numer x)))
  163.   (define (rational->real r) (make-real (/ (numer r) (denom r))))
  164.  
  165.   ;; interface to rest of the system
  166.   (define (tag x) (attach-tag 'rational x))
  167.   (put 'add    '(rational rational)  (lambda (x y) (tag (add-rat x y))))
  168.   (put 'sub    '(rational rational)  (lambda (x y) (tag (sub-rat x y))))
  169.   (put 'mul    '(rational rational)  (lambda (x y) (tag (mul-rat x y))))
  170.   (put 'div    '(rational rational)  (lambda (x y) (tag (div-rat x y))))
  171.   (put 'equ?   '(rational rational) equ-rat)
  172.   (put '=zero? '(rational) =zero-rat)
  173.   (put 'raise  '(rational) rational->real)
  174.   (put 'make   'rational (lambda (n d) (tag (make-rat n d))))
  175.   'done)
  176.  
  177.  
  178. ;; ======================================================================
  179. ;;
  180. ;; The real number package
  181. ;;
  182. ;; ======================================================================
  183. (define (install-real-package)
  184.   ;; internal procedures
  185.   (define (tag x) (attach-tag 'real x))  
  186.   (define (real->complex r) (make-complex-from-real-imag r 0))
  187.  
  188.   ;; interface to rest of the system
  189.   (put 'add    '(real real) (lambda (x y) (tag (+ x y))))
  190.   (put 'sub    '(real real) (lambda (x y) (tag (- x y))))
  191.   (put 'mul    '(real real) (lambda (x y) (tag (* x y))))
  192.   (put 'div    '(real real) (lambda (x y) (tag (/ x y))))
  193.   (put 'equ?   '(real real) =)
  194.   (put '=zero? '(real real) zero?)
  195.   (put 'raise  '(real) real->complex)
  196.   (put 'make   'real (lambda (n) (tag n)))
  197.   'done)
  198.  
  199.  
  200. ;; ======================================================================
  201. ;;
  202. ;; The rectangular number package
  203. ;;
  204. ;; ======================================================================
  205. (define (install-rectangular-package)
  206.   ;; internal procedures
  207.   (define (real-part z) (car z))
  208.   (define (imag-part z) (cdr z))
  209.   (define (make-from-real-imag x y) (cons x y))
  210.   (define (magnitude z)
  211.     (sqrt (+ (square (real-part z))
  212.              (square (imag-part z)))))
  213.   (define (angle z)
  214.     (atan (imag-part z) (real-part z)))
  215.   (define (make-from-mag-ang r a)
  216.     (cons (* r (cos a)) (* r (sin a))))
  217.   ;; interface to the rest of the system
  218.   (define (tag x) (attach-tag 'rectangular x))
  219.   (put 'real-part '(rectangular) real-part)
  220.   (put 'imag-part '(rectangular) imag-part)
  221.   (put 'magnitude '(rectangular) magnitude)
  222.   (put 'angle     '(rectangular) angle)
  223.   (put 'make-from-real-imag 'rectangular
  224.        (lambda (x y) (tag (make-from-real-imag x y))))
  225.   (put 'make-from-mag-ang 'rectangular
  226.        (lambda (r a) (tag (make-from-mag-ang r a))))
  227.   'done)
  228.  
  229. ;; ======================================================================
  230. ;;
  231. ;; The polar number package
  232. ;;
  233. ;; ======================================================================
  234. (define (install-polar-package)
  235.   ;; internal procedures
  236.   (define (magnitude z) (car z))
  237.   (define (angle z) (cdr z))
  238.   (define (make-from-mag-ang r a) (cons r a))
  239.   (define (real-part z)
  240.     (* (magnitude z) (cos (angle z))))
  241.   (define (imag-part z)
  242.     (* (magnitude z) (sin (angle z))))
  243.   (define (make-from-real-imag x y)
  244.     (cons (sqrt (+ (square x) (square y)))
  245.           (atan y x)))
  246.   ;; interface to the rest of the system
  247.   (define (tag x) (attach-tag 'polar x))
  248.   (put 'real-part '(polar) real-part)
  249.   (put 'imag-part '(polar) imag-part)
  250.   (put 'magnitude '(polar) magnitude)
  251.   (put 'angle '(polar) angle)
  252.   (put 'make-from-real-imag 'polar
  253.        (lambda (x y) (tag (make-from-real-imag x y))))
  254.   (put 'make-from-mag-ang 'polar
  255.        (lambda (r a) (tag (make-from-mag-ang r a))))
  256.   'done)
  257.  
  258.  
  259. ;; ======================================================================
  260. ;;
  261. ;; The complex number package
  262. ;;
  263. ;; ======================================================================
  264. (define (install-complex-package)
  265.   ;; imported procedures from rectangular and polar packages
  266.   (define (make-from-real-imag x y) ((get 'make-from-real-imag 'rectangular) x y))
  267.   (define (make-from-mag-ang r a) ((get 'make-from-mag-ang 'polar) r a))
  268.   ;; internal procedures
  269.   (define (tag z) (attach-tag 'complex z))
  270.   (define (add-complex z1 z2) (make-from-real-imag (+ (real-part z1) (real-part z2))
  271.                                                    (+ (imag-part z1) (imag-part z2))))
  272.   (define (sub-complex z1 z2) (make-from-real-imag (- (real-part z1) (real-part z2))
  273.                                                    (- (imag-part z1) (imag-part z2))))
  274.   (define (mul-complex z1 z2) (make-from-mag-ang (* (magnitude z1) (magnitude z2))
  275.                                                  (+ (angle z1) (angle z2))))
  276.   (define (div-complex z1 z2) (make-from-mag-ang (/ (magnitude z1) (magnitude z2))
  277.                                                  (- (angle z1) (angle z2))))
  278.   (define (equ-complex z1 z2) (and (equ? (magnitude z1) (magnitude z2))
  279.                                    (equ? (angle z1) (angle z2))))
  280.   (define (=zero-complex z1) (zero? (magnitude z1)))
  281.   ;; interface to rest of the system
  282.   (put 'add    '(complex complex) (lambda (z1 z2) (tag (add-complex z1 z2))))
  283.   (put 'sub    '(complex complex) (lambda (z1 z2) (tag (sub-complex z1 z2))))
  284.   (put 'mul    '(complex complex) (lambda (z1 z2) (tag (mul-complex z1 z2))))
  285.   (put 'div    '(complex complex) (lambda (z1 z2) (tag (div-complex z1 z2))))
  286.   (put 'equ?   '(complex complex) equ-complex)
  287.   (put '=zero? '(complex) =zero-complex)
  288.   (put 'make-from-real-imag 'complex (lambda (x y) (tag (make-from-real-imag x y))))
  289.   (put 'make-from-mag-ang 'complex (lambda (r a) (tag (make-from-mag-ang r a))))
  290.   (put 'real-part '(complex) real-part)
  291.   (put 'imag-part '(complex) imag-part)
  292.   (put 'magnitude '(complex) magnitude)
  293.   (put 'angle     '(complex) angle)
  294.   'done)
  295.  
  296.  
  297. ;; ======================================================================
  298. ;;
  299. ;; Generic procedures
  300. ;;
  301. ;; ======================================================================
  302.  
  303. ; Constructors
  304. (define (make-integer n)                  ((get 'make 'integer) n))
  305. (define (make-real n)                     ((get 'make 'real) n))
  306. (define (make-rational n d)               ((get 'make 'rational) n d))
  307. (define (make-complex-from-real-imag x y) ((get 'make-from-real-imag 'complex) x y))
  308. (define (make-complex-from-mag-ang r a)   ((get 'make-from-mag-ang 'complex) r a))
  309.  
  310. ; Selectors
  311. (define (real-part z) (apply-generic 'real-part z))
  312. (define (imag-part z) (apply-generic 'imag-part z))
  313. (define (magnitude z) (apply-generic 'magnitude z))
  314. (define (angle     z) (apply-generic 'angle     z))
  315.  
  316. ; Operators
  317. (define (add x y)     (apply-generic 'add x y))
  318. (define (sub x y)     (apply-generic 'sub x y))
  319. (define (mul x y)     (apply-generic 'mul x y))
  320. (define (div x y)     (apply-generic 'div x y))
  321. (define (equ? x y)    (apply-generic 'equ? x y))
  322. (define (=zero? x)    (apply-generic '=zero? x))
  323. (define (raise x)     (apply-generic 'raise x))
  324.  
  325. ;; ======================================================================
  326. ;;
  327. ;; Package installation
  328. ;;
  329. ;; ======================================================================
  330. (define (install-number-packages)
  331.   (install-integer-package)
  332.   (install-polar-package)
  333.   (install-rectangular-package)
  334.   (install-rational-package)
  335.   (install-real-package)
  336.   (install-complex-package))  
  337.  
  338. (install-number-packages)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement