/racket/ex-2.83.rkt

http://github.com/jevgeni/sicp-study · Racket · 220 lines · 190 code · 10 blank · 20 comment · 5 complexity · 273e520a8f5c3966e45133a179a6284d MD5 · raw file

  1. #lang racket
  2. (define h (make-hash))
  3. (define (put op type element)
  4. (dict-set! h (list op type) element))
  5. (define (get op type)
  6. (dict-ref h (list op type) false))
  7. ;-------------------------------------------------
  8. (define h2 (make-hash))
  9. (define (put-coercion op type element)
  10. (dict-set! h2 (list op type) element))
  11. (define (get-coercion op type)
  12. (dict-ref h2 (list op type) false))
  13. ;-------------------------------------------------
  14. (define (attach-tag type-tag contents)
  15. (cons type-tag contents))
  16. (define (type-tag datum)
  17. (cond ((pair? datum) (car datum))
  18. (else (error "Incorrectly marked data -- TYPE-TAG" datum))))
  19. (define (contents datum)
  20. (cond ((pair? datum) (cdr datum))
  21. (else (error "Incorrectly marked data -- CONTENTS" datum))))
  22. ;-------------------------------------------------
  23. (define (install-scheme-number-package)
  24. (define (tag x)
  25. (attach-tag 'scheme-number x))
  26. (put 'add '(scheme-number scheme-number)
  27. (lambda (x y) (tag (+ x y))))
  28. (put 'sub '(scheme-number scheme-number)
  29. (lambda (x y) (tag (- x y))))
  30. (put 'mul '(scheme-number scheme-number)
  31. (lambda (x y) (tag (* x y))))
  32. (put 'div '(scheme-number scheme-number)
  33. (lambda (x y) (tag (/ x y))))
  34. (put 'make 'scheme-number
  35. (lambda (x) (tag x)))
  36. 'done)
  37. (define (make-scheme-number n)
  38. ((get 'make 'scheme-number) n))
  39. ;-------------------------------------------------
  40. (define (install-rational-package)
  41. ;; internal procedures
  42. (define (numer x) (car x))
  43. (define (denom x) (cdr x))
  44. (define (make-rat n d)
  45. (let ((g (gcd n d)))
  46. (cons (/ n g) (/ d g))))
  47. (define (add-rat x y)
  48. (make-rat (+ (* (numer x) (denom y))
  49. (* (numer y) (denom x)))
  50. (* (denom x) (denom y))))
  51. (define (sub-rat x y)
  52. (make-rat (- (* (numer x) (denom y))
  53. (* (numer y) (denom x)))
  54. (* (denom x) (denom y))))
  55. (define (mul-rat x y)
  56. (make-rat (* (numer x) (numer y))
  57. (* (denom x) (denom y))))
  58. (define (div-rat x y)
  59. (make-rat (* (numer x) (denom y))
  60. (* (denom x) (numer y))))
  61. ;; interface to rest of the system
  62. (define (tag x) (attach-tag 'rational x))
  63. (put 'add '(rational rational)
  64. (lambda (x y) (tag (add-rat x y))))
  65. (put 'sub '(rational rational)
  66. (lambda (x y) (tag (sub-rat x y))))
  67. (put 'mul '(rational rational)
  68. (lambda (x y) (tag (mul-rat x y))))
  69. (put 'div '(rational rational)
  70. (lambda (x y) (tag (div-rat x y))))
  71. (put 'make 'rational
  72. (lambda (n d) (tag (make-rat n d))))
  73. 'done)
  74. (define (make-rational n d)
  75. ((get 'make 'rational) n d))
  76. ;-----------------------------------------------
  77. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  78. (define (install-rectangular-package)
  79. ;; internal procedures
  80. (define (real-part z) (car z))
  81. (define (imag-part z) (cdr z))
  82. (define (make-from-real-imag x y) (cons x y))
  83. (define (magnitude z)
  84. (sqrt (+ (sqr (real-part z))
  85. (sqr (imag-part z)))))
  86. (define (angle z)
  87. (atan (imag-part z) (real-part z)))
  88. (define (make-from-mag-ang r a)
  89. (cons (* r (cos a)) (* r (sin a))))
  90. ;; interface to the rest of the system
  91. (define (tag x) (attach-tag 'rectangular x))
  92. (put 'real-part '(rectangular) real-part)
  93. (put 'imag-part '(rectangular) imag-part)
  94. (put 'magnitude '(rectangular) magnitude)
  95. (put 'angle '(rectangular) angle)
  96. (put 'make-from-real-imag 'rectangular
  97. (lambda (x y) (tag (make-from-real-imag x y))))
  98. (put 'make-from-mag-ang 'rectangular
  99. (lambda (r a) (tag (make-from-mag-ang r a))))
  100. 'done)
  101. (define (make-real n d)
  102. ((get 'make-from-real-imag 'rectangular) n d))
  103. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  104. (define (install-polar-package)
  105. ;; internal procedures
  106. (define (magnitude z) (car z))
  107. (define (angle z) (cdr z))
  108. (define (make-from-mag-ang r a) (cons r a))
  109. (define (real-part z)
  110. (* (magnitude z) (cos (angle z))))
  111. (define (imag-part z)
  112. (* (magnitude z) (sin (angle z))))
  113. (define (make-from-real-imag x y)
  114. (cons (sqrt (+ (sqr x) (sqr y)))
  115. (atan y x)))
  116. ;; interface to the rest of the system
  117. (define (tag x) (attach-tag 'polar x))
  118. (put 'real-part '(polar) real-part)
  119. (put 'imag-part '(polar) imag-part)
  120. (put 'magnitude '(polar) magnitude)
  121. (put 'angle '(polar) angle)
  122. (put 'make-from-real-imag 'polar
  123. (lambda (x y) (tag (make-from-real-imag x y))))
  124. (put 'make-from-mag-ang 'polar
  125. (lambda (r a) (tag (make-from-mag-ang r a))))
  126. 'done)
  127. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  128. (define (install-complex-package)
  129. ;; imported procedures from rectangular and polar packages
  130. (define (make-from-real-imag x y)
  131. ((get 'make-from-real-imag 'rectangular) x y))
  132. (define (make-from-mag-ang r a)
  133. ((get 'make-from-mag-ang 'polar) r a))
  134. ;; internal procedures
  135. (define (add-complex z1 z2)
  136. (make-from-real-imag (+ (real-part z1) (real-part z2))
  137. (+ (imag-part z1) (imag-part z2))))
  138. (define (sub-complex z1 z2)
  139. (make-from-real-imag (- (real-part z1) (real-part z2))
  140. (- (imag-part z1) (imag-part z2))))
  141. (define (mul-complex z1 z2)
  142. (make-from-mag-ang (* (magnitude z1) (magnitude z2))
  143. (+ (angle z1) (angle z2))))
  144. (define (div-complex z1 z2)
  145. (make-from-mag-ang (/ (magnitude z1) (magnitude z2))
  146. (- (angle z1) (angle z2))))
  147. ;; interface to rest of the system
  148. (define (tag z) (attach-tag 'complex z))
  149. (put 'add '(complex complex)
  150. (lambda (z1 z2) (tag (add-complex z1 z2))))
  151. (put 'sub '(complex complex)
  152. (lambda (z1 z2) (tag (sub-complex z1 z2))))
  153. (put 'mul '(complex complex)
  154. (lambda (z1 z2) (tag (mul-complex z1 z2))))
  155. (put 'div '(complex complex)
  156. (lambda (z1 z2) (tag (div-complex z1 z2))))
  157. (put 'make-from-real-imag 'complex
  158. (lambda (x y) (tag (make-from-real-imag x y))))
  159. (put 'make-from-mag-ang 'complex
  160. (lambda (r a) (tag (make-from-mag-ang r a))))
  161. 'done)
  162. (define (make-complex-from-real-imag x y)
  163. ((get 'make-from-real-imag 'complex) x y))
  164. (define (make-complex-from-mag-ang r a)
  165. ((get 'make-from-mag-ang 'complex) r a))
  166. ;------------------------------------------------
  167. (install-scheme-number-package)
  168. (install-rational-package)
  169. (install-rectangular-package)
  170. (install-polar-package)
  171. (install-complex-package)
  172. ;------------------------------------------------
  173. (define (apply-generic op . args)
  174. (let ((type-tags (map type-tag args)))
  175. (let ((proc (get op type-tags)))
  176. (if proc
  177. (apply proc (map contents args))
  178. (if (= (length args) 2)
  179. (let ((type1 (car type-tags))
  180. (type2 (cadr type-tags))
  181. (a1 (car args))
  182. (a2 (cadr args)))
  183. (let ((t1->t2 (get-coercion type1 type2))
  184. (t2->t1 (get-coercion type2 type1)))
  185. (cond (t1->t2
  186. (apply-generic op (t1->t2 a1) a2))
  187. (t2->t1
  188. (apply-generic op a1 (t2->t1 a2)))
  189. (else
  190. (error "No method for these types"
  191. (list op type-tags))))))
  192. (error "No method for these types"
  193. (list op type-tags)))))))
  194. ;--------------------------------------------------
  195. (define (integer->rational n) (make-rational n 1))
  196. (define (rational->real n)
  197. (let ((numer (car n))
  198. (denum (cdr n)))
  199. (make-real (/ numer denum 1.0)0)))
  200. (define (real->complex n) (make-complex-from-real-imag (car n) 0))
  201. (put 'raise '(scheme-number) integer->rational)
  202. (put 'raise '(rational) rational->real)
  203. (put 'raise '(rectangular) real->complex)
  204. (define (raise n) (apply-generic 'raise n))
  205. (raise (make-scheme-number 4))
  206. '(rational 4 . 1)
  207. (raise(raise (make-scheme-number 4)))
  208. '(rectangular 4.0 . 0)
  209. (raise (raise(raise (make-scheme-number 4))))
  210. '(complex rectangular 4.0 . 0)